具有多个文本框的用户控件'聚合成 DependencyProperty
我正在尝试构建一个本质上是 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 地址的字符串)并使每个八位字节显示在其自己的文本框中。然后,如果任何八位字节文本框发生更改,IPAddress 依赖属性将更新。
这可能吗?我是否以正确的方式思考这个问题?
I'm trying to build a UserControl that is essentially an IPv4 Address 'text box'.
In the UserControl there are 4 TextBoxes, with a TextBlock containing a single "." between each 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>
My hope is that I can have a DependencyProperty called IPAddress on the control that I can bind to, or set a default value in XAML "123.123.123.123".
<local:IPBox IPAddress="123.123.123.123" />
I thought that I could use something like MultiBinding and an 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('.');
}
}
But I believe that would be doing the opposite of what I want. A MultiValueConverter would merge multiple business logic properties into a single property for a TextBox to bind to.
Instead, I want to bind a single business logic property (a string representing an IPv4 Address) and have each Octet show up in its own TextBox. Then if any of the Octet TextBoxes change, the IPAddress dependency property will update.
Is this possible? Am I thinking about this problem in the right way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有很多方法可以做到这一点。只需为八位位组创建私有属性并将文本框绑定到这些属性,例如:
然后实现更新依赖属性的设置器:
编辑:
双向绑定有点棘手,因为您需要更改通知以更新 UI。我处理这个问题的方法可能是创建一个具有八位字节和 IP 地址属性并实现 INotifyPropertyChanged 的视图模型类,然后在 UserControl 的构造函数中创建它的实例并绑定所有 UI控制属性。这样,当视图模型上的
IPAddress
被设置时,setter 可以解析该值,更新八位组属性,并引发PropertyChanged
并且 UI 得到更新。然后在
UserControl
中,我将处理视图模型上的PropertyChanged
并在控件上设置IPAddress
依赖属性 > 当视图模型上的IPAddress1
属性发生变化时。 (这并不像听起来那么奇怪。)您还需要编写一个函数,将视图模型的
IPAddress
属性设置为IPAddress
依赖项属性的值,并将该函数设置为回调,当您注册 DP。
因此,事件链将是:设置控件上的
IPAddress
属性 -> DP 回调在视图模型上设置IPAddress
属性 ->IPAddress
setter 解析八位字节并设置Octet
属性 ->Octet
属性引发PropertyChanged
->绑定将更改的值推送到UserControl
中的 UI 控件。换句话说,就是:用户输入一个八位字节 ->八位字节设置器在视图模型上设置IPAddress
->用户控件处理PropertyChanged
并设置IPAddress
依赖属性。There are a lot of ways to do this. One's simply to create private properties for the octet and bind the text boxes to those properties, e.g.:
and then implement setters that update the dependency property:
Edit:
Two-way binding is a little tricky because you need change notification in order to update the UI. The way I'd handle this, probably, is to create a view model class that has octet and IP address properties and implements
INotifyPropertyChanged
, then create an instance of it in the UserControl's constructor and bind all the UI controls to the properties. That way when theIPAddress
on the view model gets set, the setter can parse the value, update the octet properties, and they raisePropertyChanged
and the UI gets updated.Then in the
UserControl
, I'd handlePropertyChanged
on the view model and set theIPAddress
dependency property on the control when theIPAddress1
property on the view model changes. (That isn't as weird as it sounds.)You'll also need to write a function that sets the view model's
IPAddress
property to the value of theIPAddress
dependency property, and set that function as a callback when youregister the DP.
So the chain of events will be: something sets the
IPAddress
property on the control -> the DP callback sets theIPAddress
property on the view model -> theIPAddress
setter parses the octets and sets theOctet
properties -> theOctet
properties raisePropertyChanged
-> binding pushes the changed values out to the UI controls in yourUserControl
. Going the other way, it's: user enters an octet -> octet setter setsIPAddress
on the view model -> user control handlesPropertyChanged
and sets theIPAddress
dependency property.