开发者

UserControl with multiple TextBoxes' that aggregate into a DependencyProperty

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜