繁体   English   中英

WPF与用户控件的数据绑定

[英]WPF databinding with a user control

我有一个wpf用户控件,它公开了一个自定义依赖项属性。 在用户控件内,文本块绑定到dp的值。 此数据绑定适用于所有方案,除非数据源是对象。

重现这个的最小代码是:

这是用户控件的主要部分

<StackPanel Orientation="Horizontal">
    <TextBlock Text="**SimpleUC** UCValue: "/>
    <TextBlock Text="{Binding UCValue}"/>
</StackPanel>

以及后面的用户控制代码:

    public SimpleUC()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public string UCValue
    {
        get { return (string)GetValue(UCValueProperty); }
        set { SetValue(UCValueProperty, value); }
    }

    public static readonly DependencyProperty UCValueProperty =
        DependencyProperty.Register("UCValue", typeof(string), typeof(SimpleUC), new UIPropertyMetadata("value not set"));

这是测试窗口。 我将项目xml命名空间导入为“custom”

<Window.Resources>
    <Style TargetType="{x:Type StackPanel}">
        <Setter Property="Margin" Value="20"/>
    </Style>
</Window.Resources>
<StackPanel>
    <StackPanel>
        <TextBlock Text="This fails to bind:"/>
        <custom:SimpleUC UCValue="{Binding SomeData}"/> 
    </StackPanel>
    <StackPanel>
        <TextBlock>The same binding on a regular control like Label</TextBlock>
        <Label Content="{Binding SomeData}"/>
    </StackPanel>
    <Slider x:Name="sld" />
    <StackPanel>
        <TextBlock>However, binding the UC to another element value, like a slider works</TextBlock>
        <custom:SimpleUC UCValue="{Binding ElementName=sld,Path=Value}"/>
    </StackPanel>
</StackPanel>

并且后面的测试窗口代码是:

public TestWindow()
{
    InitializeComponent();
    this.DataContext = this;
}

//property to bind to
public string SomeData { get { return "Hello S.O."; } } 

当我打开TestWindow上的诊断跟踪时,它会发出错误“BindingExpression path error: 'SomeData' property not found on 'object' ''SimpleUC' (Name='')' ... "
绑定表达式与我在相邻标签中使用的表达式相同,并且工作正常。 这种行为对我来说似乎很奇怪。 任何人都能解释一下吗?

您可以在此处将SimpleUC的DataContext设置为自身

public SimpleUC()
{
    InitializeComponent();
    this.DataContext = this; // wrong way!
}

所以当你在这里使用绑定

<custom:SimpleUC UCValue="{Binding SomeData}"/>

它在控件的数据上下文中搜索属性SomeData,该上下文设置为此对象,因为SimpleUC构造函数中的代码会覆盖DataContext的值,并且不再按预期将其设置为TestWindow对象。 这就是您的解决方案有效的原因 - 它不会影响从窗口继承的DataContext。 你也可以保留this.DataContext = this; 但设置元素在哪里显式搜索属性(跳过不相关)

<Window ... Name="wnd1">
    <custom:SimpleUC UCValue="{Binding SomeData, ElementName=wnd1}"/>
...

但我的观点是,你的答案中的变体看起来对我来说更方便,设置数据上下文对此并不是很好的做法。

希望能帮助到你。

如果你必须使用UserControl ,你的

<TextBlock
  Text="{Binding RelativeSource={RelativeSource Self},
                 Path=Parent.Parent.UCValue}"
/>

这是一个很好的方法来做到这一点

<TextBlock
  Text="{Binding UCValue,
                 RelativeSource={RelativeSource FindAncestor,custom:SimpleUC,1}}"
/>

更好,因为您不依赖于控件层次结构和可能的实例化顺序问题。

但是,我建议您使用“自定义控件”而不是“用户控件”来处理这种情况。 他们需要一点点习惯,但它们更强大,因为他们的XAML本身就是模板,这意味着你可以使用TemplateBinding{RelativeSource TemplatedParent}

在任何情况下, DataContext = this; 绝对是要避免的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM