WPF用户控件中的数据绑定

Gab*_*tin 32 c# data-binding wpf xaml user-controls

我正在为几个窗口共享的一系列控件创建一个UserControl.其中一个控件是Label,它根据"协议编号"显示其他一些过程的流程.

我正在尝试使用此Label提供DataBinding,因此Window会在协议编号变量更改时自动反映进程的状态.

这是用户控件XAML:

<UserControl Name="MainOptionsPanel"
    x:Class="ExperienceMainControls.MainControls"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    >
<Label Height="Auto" Name="numberLabel">Protocol:</Label>
<Label Content="{Binding Path=ProtocolNumber}" Name="protocolNumberLabel"/>
(...)
</UserControl>
Run Code Online (Sandbox Code Playgroud)

这就是Code-Behind:

public partial class MainControls 
{
    public MainControls()
    {
        InitializeComponent();
    }

    public int ProtocolNumber
    {
        get { return (int)GetValue(ProtocolNumberProperty); }
        set { SetValue(ProtocolNumberProperty, value); }
    }

    public static DependencyProperty ProtocolNumberProperty = 
       DependencyProperty.Register("ProtocolNumber", typeof(int), typeof(MainControls));
}
Run Code Online (Sandbox Code Playgroud)

这似乎是有效的,因为如果在构造函数中我将ProtocolNumber设置为任意值,它将反映在用户控件中.

但是,在最终窗口上使用此用户控件时,数据绑定会中断.

XAML:

<Window x:Class="UserControlTesting.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:expControl="clr-namespace:ExperienceMainControls;assembly=ExperienceMainControls"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    >
    <StackPanel>
        <expControl:MainControls ProtocolNumber="{Binding Path=Number, Mode=TwoWay}" />
    </StackPanel>

</Window>
Run Code Online (Sandbox Code Playgroud)

窗口的代码隐藏:

public partial class Window1 : Window
{
    public Window1()
    {
        Number= 15;
        InitializeComponent();
    }

    public int Number { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这会将协议编号设置为零,忽略设置为Number的值.

我看过这个例子

bli*_*eis 39

如果你查看输出窗口,你应该看到绑定异常.

您遇到的问题如下:在您的usercontrol中,您将标签绑定到您的usercontrol的DP ProtocolNumber而不是DataContext,所以您必须添加例如绑定的元素名称.

<UserControl Name="MainOptionsPanel"
    x:Class="ExperienceMainControls.MainControls"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="uc"
    >
<Label Height="Auto" Name="numberLabel">Protocol:</Label>
<Label Content="{Binding Path=ProtocolNumber, ElementName=uc}" Name="protocolNumberLabel"/>
(...)
</UserControl>
Run Code Online (Sandbox Code Playgroud)

编辑:要清除一些内容,如果更改MainWindow中的绑定,则usercontrol也可以正常工作.但是你必须使用RelativeSource绑定到MainWindow的DataContext.

    <expControl:MainControls ProtocolNumber="{Binding Path=Number, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
Run Code Online (Sandbox Code Playgroud)


H.B*_*.B. 6

你有什么效果:

<expControl:MainControls DataContext="{Binding RelativeSource={RelativeSource Self}}"
                         ProtocolNumber="{Binding Path=Number, Mode=TwoWay}"/>
Run Code Online (Sandbox Code Playgroud)

=>千万不能设置DataContextUserControl声明中,使用RelativeSourceElementName绑定来代替.

  • 为什么不设置DataContext?我知道有一些方法可以传播到子控件(我想),但到目前为止我们还没有遇到任何麻烦. (3认同)
  • @mizipzor:这是一种不好的做法,将DataContext设置为“从外部”是不可见的,并且不切实际,因为通常想要并期望继承DataContext。 (2认同)
  • 实际上,DataContext的继承(到目前为止)不是我想要的。CustomControls是另一个故事。但是对于UserControls,我将争论其良好做法。 (2认同)
  • @kelmer:是的。这不是同一个对象,您在定义中所做的任何事情都将应用于您的实例,正如刚刚所示,在设置DataContext的情况下,这是一个坏主意,因为它会覆盖继承的DataContext。 (2认同)