【问题标题】:UserControl with multiple TextBoxes' that aggregate into a DependencyProperty具有多个 TextBoxes 的 UserControl 聚合成一个 DependencyProperty
【发布时间】:2011-08-26 14:55:59
【问题描述】:

我正在尝试构建一个本质上是 IPv4 地址“文本框”的 UserControl。

在 UserControl 中有 4 个 TextBox,其中一个 TextBlock 包含一个“.”。每个文本框之间:

<Grid Grid.IsSharedSizeScope="True">
    <Grid.ColumnDefinitions>
        <ColumnDefinition SharedSizeGroup="GroupA" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition SharedSizeGroup="GroupA" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition SharedSizeGroup="GroupA" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition SharedSizeGroup="GroupA" />
    </Grid.ColumnDefinitions>
    <TextBox Grid.Column="0" TabIndex="0" x:Name="TextOctet1" />
    <TextBlock Grid.Column="1" Text="." />
    <TextBox Grid.Column="2" TabIndex="1" x:Name="TextOctet2" />
    <TextBlock Grid.Column="3" Text="." />
    <TextBox Grid.Column="4" TabIndex="2" x:Name="TextOctet3" />
    <TextBlock Grid.Column="5" Text="." />
    <TextBox Grid.Column="6" TabIndex="3" x:Name="TextOctet4" />
</Grid>

我希望我可以在我可以绑定到的控件上拥有一个名为 IPAddress 的 DependencyProperty,或者在 XAML“123.123.123.123”中设置一个默认值。

<local:IPBox IPAddress="123.123.123.123" />

我认为我可以使用 MultiBinding 和 IMultiValueConverter 之类的东西:

public class IPAddressConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return String.Format("{0}.{1}.{2}.{3}", values[0], values[1], values[2], values[3]);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((string)value).Split('.');
    }
}

但我相信这与我想要的相反。 MultiValueConverter 会将多个业务逻辑属性合并为一个属性,供 TextBox 绑定。

相反,我想绑定一个业务逻辑属性(表示 IPv4 地址的字符串)并让每个八位字节显示在其自己的文本框中。然后,如果任何 Octet TextBoxes 发生变化,IPAddress 依赖属性将更新。

这可能吗?我是否以正确的方式思考这个问题?

【问题讨论】:

    标签: wpf user-controls binding ip-address dependency-properties


    【解决方案1】:

    有很多方法可以做到这一点。只需为八位字节创建私有属性并将文本框绑定到这些属性,例如:

    <TextBox Text={Binding RelativeSource={AncestorType UserControl}, Path=Octet1}, Mode=TwoWay"/>
    

    然后实现更新依赖属性的设置器:

    private int _Octet1;
    private int Octet1
    {
       get { return _Octet1; }
       set
       {
         _Octet1 = value;
         UpdateIPAddress();
       }
    }
    
    private void UpdateIPAddress()
    {
       IPAddress = string.Format("{0}.{1}.{2}.{3}", _Octet1, _Octet2, _Octet3, _Octet4);
    }
    

    编辑:

    双向绑定有点棘手,因为您需要更改通知才能更新 UI。我处理这个问题的方法可能是创建一个具有八位字节和 IP 地址属性并实现INotifyPropertyChanged 的视图模型类,然后在 UserControl 的构造函数中创建它的一个实例并将所有 UI 控件绑定到属性。这样,当视图模型上的 IPAddress 被设置时,setter 可以解析值,更新八位字节属性,并引发 PropertyChanged 并更新 UI。

    然后在UserControl 中,我会在视图模型上处理PropertyChanged 并在 控件上设置IPAddress 依赖属性,而查看模型 的变化。 (这并不像听起来那么奇怪。)

    您还需要编写一个函数,将视图模型的 IPAddress 属性设置为 IPAddress 依赖项属性的值,然后将该函数设置为回调 注册DP。

    所以事件链将是:在控件上设置 IPAddress 属性 -> DP 回调在视图模型上设置 IPAddress 属性 -> IPAddress setter 解析八位字节并设置 @ 987654335@ 属性 -> Octet 属性引发 PropertyChanged -> 绑定将更改的值推送到 UserControl 中的 UI 控件。换一种方式,它是:用户输入一个八位字节 -> 八位字节设置器在视图模型上设置 IPAddress -> 用户控件处理 PropertyChanged 并设置 IPAddress 依赖属性。

    【讨论】:

    • 如果我将我的 UserControl 的 IPAddress 依赖属性绑定到一些正确格式的字符串,八位字节如何更新? (双向绑定):
    • 那我觉得你需要实现一个视图模型。查看我的编辑。
    • 哈......所以我第一次尝试了所有这些东西......但它就是行不通。我后来发现,当我绑定到已经与默认数据具有相同值的数据时,我的 dp 中有默认数据导致它显示为空白: public static readonly DependencyProperty IPAddressProperty = DependencyProperty.Register("IPAddress", typeof(string), typeof(IPBox), new UIPropertyMetadata("0.0.0.0", new PropertyChangedCallback(IPAddressChanged)));.一旦我删除“0.0.0.0”,一切就开始工作了。感谢您抽出宝贵时间查看并帮助我!
    猜你喜欢
    • 1970-01-01
    • 2016-04-21
    • 2018-10-24
    • 2020-10-02
    • 1970-01-01
    • 2021-11-06
    • 2014-05-03
    • 2011-06-29
    • 2012-03-02
    相关资源
    最近更新 更多