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="12开发者_Python百科3.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?
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.:
<TextBox Text={Binding RelativeSource={AncestorType UserControl}, Path=Octet1}, Mode=TwoWay"/>
and then implement setters that update the dependency property:
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);
}
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 the IPAddress
on the view model gets set, the setter can parse the value, update the octet properties, and they raise PropertyChanged
and the UI gets updated.
Then in the UserControl
, I'd handle PropertyChanged
on the view model and set the IPAddress
dependency property on the control when the IPAddress1
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 the IPAddress
dependency property, and set that function as a callback when you
register the DP.
So the chain of events will be: something sets the IPAddress
property on the control -> the DP callback sets the IPAddress
property on the view model -> the IPAddress
setter parses the octets and sets the Octet
properties -> the Octet
properties raise PropertyChanged
-> binding pushes the changed values out to the UI controls in your UserControl
. Going the other way, it's: user enters an octet -> octet setter sets IPAddress
on the view model -> user control handles PropertyChanged
and sets the IPAddress
dependency property.
精彩评论