如何绑定用户控件的DataContext?

时间:2018-06-15 09:50:30

标签: data-binding user-controls datacontext

我有这样的用户控件:

<UserControl x:Class="IPAddressWPFUserControl.IPAddressControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" BorderThickness="0" OverridesDefaultStyle="False" BorderBrush="{x:Null}">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="auto" />
    </Grid.ColumnDefinitions>
    <TextBox  Grid.Column="0"  x:Name="txtboxFirstPart" TextChanged="txtbox_TextChanged" MaxLength="3" BorderThickness="0" TabIndex="1" PreviewKeyDown="txtboxFirstPart_PreviewKeyDown" PreviewKeyUp="txtboxFirstPart_PreviewKeyUp" Width="31" />
    <Label Content="." Grid.Column="1"   x:Name="label1" VerticalContentAlignment="Bottom" HorizontalAlignment="Left" Background="White" />
    <TextBox Grid.Column="2" x:Name="txtboxSecondPart" MaxLength="3" TextChanged="txtbox_TextChanged" BorderThickness="0" TabIndex="2" KeyDown="txtboxSecondPart_KeyDown" PreviewKeyUp="txtboxSecondPart_PreviewKeyUp" Margin="0" HorizontalAlignment="Left" Width="31"/>
    <Label Content="." Grid.Column="3" Grid.Row="0" x:Name="label2" VerticalContentAlignment="Bottom" HorizontalAlignment="Left" Background="White" />
    <TextBox  Grid.Column="4" x:Name="txtboxThridPart" MaxLength="3" TextChanged="txtbox_TextChanged" BorderThickness="0" TabIndex="3" VerticalContentAlignment="Bottom"  KeyDown="txtboxThridPart_KeyDown" PreviewKeyUp="txtboxThridPart_PreviewKeyUp" Width="31" HorizontalContentAlignment="Center" />
    <Label Content="." Grid.Column="5" x:Name="label3" VerticalContentAlignment="Bottom" HorizontalAlignment="Left" Background="White" />
    <TextBox  Grid.Column="6" x:Name="txtboxFourthPart" MaxLength="3" TextChanged="txtbox_TextChanged" BorderThickness="0" TabIndex="4" VerticalContentAlignment="Bottom" HorizontalAlignment="Left" Width="31" HorizontalContentAlignment="Center" />
</Grid>

在后面的代码中添加文字属性:

public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(IPAddressControl),
                                                             new PropertyMetadata("0.0.0.0", new PropertyChangedCallback(OnTextPropertyChanged)));
private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    IPAddressControl o = d as IPAddressControl;
    try
    {
        var value = e.NewValue as string;
        var splitValues = new string[4];
        if (value != null)
        {
            var splits = value.Split(new char[] { '.' }, StringSplitOptions.None);
            Array.Copy(splits, splitValues, splits.Length);
        }
        o.txtboxFirstPart.Text = splitValues[0];
        o.txtboxSecondPart.Text = splitValues[1];
        o.txtboxThridPart.Text = splitValues[2];
        o.txtboxFourthPart.Text = splitValues[3];
    }
    catch (Exception ex)
    {
        throw new Exception("Error in IP control see inner exception!", ex);
    }
    o.RaiseTextChanged(e);
}

public string Text
{
    get { return (string)this.GetValue(IPAddressControl.TextProperty); }
    set { this.SetValue(IPAddressControl.TextProperty, value); }
}

public event DependencyPropertyChangedEventHandler TextChanged;
protected virtual void RaiseTextChanged(DependencyPropertyChangedEventArgs e)
{
    if (this.TextChanged != null)
    {
        this.TextChanged(this, e);
    }
}

当我在MainWindow中使用它时:

<GroupBox Name="gb_Tcp" DataContext="{Binding TcpCollection}">
   <my:IPAddressControl x:Name="tb_IpAddress" Text="{Binding Path=IpAddress, ElementName=gb_tcp}"/>   
   <TextBox x:Name="tb_Test" Text={Binding Path=IpAddress, ElementName=gb_tcp}" />
</GroupBox>

问题是当我尝试在按钮点击事件中设置值时:

private void btn_IpReset_Click(object sender, RoutedEventArgs e)
{
     tb_IpAddress.Text = source.IpAddress;  //This failed to change
     tb_Test.Text= source.IpAddress;        //This changed successfully
}

我想这是因为用户控件没有将datacontext更改为MainWindow?或者可能是什么问题?提前致谢!

1 个答案:

答案 0 :(得分:0)

这是因为您没有使用BindingMode来更新TwoWayOneWayToSource之类的源。因此,在tb_IpAddress.Text = source.IpAddress之后,您设置的绑定将被本地值覆盖。 tb_Test.Text= source.IpAddress之所以有效,是因为TextBox.Text的默认绑定模式是TwoWay