我正在尝试构建一个基本上是IPv4地址'文本框'的UserControl。
在UserControl中有4个TextBox,其中TextBlock包含单个“。”。在每个TextBox之间:
<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显示在自己的TextBox中。然后,如果任何Octet TextBox更改,则IPAddress依赖项属性将更新。
这可能吗?我是否以正确的方式思考这个问题?
答案 0 :(得分:1)
有很多方法可以做到这一点。一个是简单地为八位字节创建私有属性并将文本框绑定到那些属性,例如:
<TextBox Text={Binding RelativeSource={AncestorType UserControl}, Path=Octet1}, Mode=TwoWay"/>
然后实现更新依赖项属性的setter:
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
并在{{1>时设置IPAddress
依赖属性在控件上视图模型上的属性更改。 (这并不像听起来那么奇怪。)
您还需要编写一个函数,将视图模型的IPAddress1
属性设置为IPAddress
依赖项属性的值,并将该函数设置为回调
注册DP。
所以事件链将是:某些东西在控件上设置IPAddress
属性 - &gt; DP回调在视图模型上设置IPAddress
属性 - &gt; IPAddress
setter解析八位字节并设置IPAddress
属性 - &gt; Octet
属性提升Octet
- &gt;绑定将更改后的值推送到PropertyChanged
中的UI控件。另一方面,它是:用户输入一个八位位组 - &gt; octet setter在视图模型上设置UserControl
- &gt;用户控件处理IPAddress
并设置PropertyChanged
依赖项属性。