链接DataContext与WPF中的另一个属性



事情是我总是想绑定控件对DataContext属性。因为我不喜欢在绑定表达式中指定源。但是,我不想显式地绑定控件的DataContext属性,而是使用另一个指定的和自描述的属性,如Items或Plugins或任何控件的目的。现在,我需要一种方法来设置DataContext属性,每当该自描述属性真正确定控件的上下文设置时。此外,我希望DataContext始终与此属性相同。如何做到这一点?

我尝试用回调指定PropertyMetadata,该回调将在新接收的值上设置DataContext。这行不通。首先,因为这个回调不是为属性的默认值调用的。其次,也是最有趣的一点,我观察到一些非常奇怪的行为。让我用callstack来解释一下:

这是我的PropertyMetadata在回调断点:

new PropertyMetadata((d, e) => ((SearchSettings)d).DataContext = e.NewValue)

这是调用栈(行尾有注释):

3. Bla-bla-bla.SearchSettings..cctor.AnonymousMethod__7(DependencyObject d, DependencyPropertyChangedEventArgs e) /* Setting property back to null. Why??? */
2. [External Code]  
1. Bla-bla-bla.SearchSettings..cctor.AnonymousMethod__7(DependencyObject d, DependencyPropertyChangedEventArgs e) /* This is where the breakpoint hit first. Settings a new value to a property as a result of databinding. */

那么,我怎么做呢?或者我应该做这件事吗?顺便说一句,我是WPF的新手,所以我可能会错的。

根据您最近一个问题的答案,DataContext是绑定将用作其数据源的对象。

当我建议将DataContext设置为页面或控件时(下面,在原始答案中),这样您就不必像原始问题中所述的那样在Binding中指定Source属性。

示例 -而不是像

那样指定绑定:

{Binding Path=PropertyName, RelativeSource={RelativeSource AncestorType={x:Type ns:ControlName}}}

你可以直接用

{Binding Path=PropertyName}

作为容器DataContext属性被设置为ControlName的实例(这仅适用于指定DataContext = this而不是 DataContext = this.DataContext,因为这将只是将其设置为自身并且毫无意义)。

现在对于PageWindow对象,PropertyName可以是寄存器DependencyProperty实例,也可以是股票标准Property,引发INotifyPropertyChanged.PropertyChanged事件,通知XAML中的子节点属性已经更改,并根据需要更新自己。

对于Control对象,您仍然可以使用任何一种方法-但是,如果您希望能够绑定到这些属性,则需要将它们定义为DependencyProperty s。

你能更新你的文章与任何来源为我们看你吗?


原始答:

我不完全确定我理解了您的最终目标,但是为您的控件指定DataContext的最懒惰的方法是在构造函数中将页面的DataContext属性设置为它自己。

this.DataContext = this;

这消除了在绑定中设置Source和RelativeSource属性的需要,同时仍然允许您直接绑定到页面属性。

的例子:

public class MyControl : UserControl
{
    public static readonly DependencyProperty SomeStringProperty = DependencyProperty.Register("SomeString", typeof(string), typeof(ownerclass), new UIPropertyMetadata(0));
    public string SomeString
    {
        get { return (string)GetValue(SomeStringProperty); }
        set { SetValue(SomeStringProperty, value); }
    }
    public MyControl()
    {
        InitializeComponent();
        DataContext = this;
    }
}
然后在XAML中:

<TextBlock Text="{Binding Path=SomeString}" />

我真的不明白为什么要创建一个属性来代替DataContext

DataContext的目的是引用控件背后的实际数据。为什么要为一个已经存在的属性创建第二个属性呢?对我来说,这就像说你想重写控件的IsReadOnly属性,所以它读DisableEditing -没有目的。

此外,为什么要将其绑定到应用层?WPF的全部意义在于将业务/应用程序逻辑从UI中分离出来,而您要做的就是将两者结合在一起。如果你想要这种行为,请使用WinForms。

如果您想确保您的UserControl仅与User DataContext一起使用,请使用DataTemplate

<DataTemplate DataType="{x:Type local:User}">
    <local:MyUserControl /> <!-- DataContext will be User -->
</DataTemplate>
<!-- This will display a User object, but because of the DataTemplate it will 
     draw it using your UserControl instead of the default User.ToString() -->
<ContentControl Content="{Binding CurrentUser}" /> 

如果你真的想确保你的UserControl只接收User对象作为DataContext,在初始化this.DataContextUser对象时做一些验证检查。不要创建某种自定义属性,人们需要记住在他们想要使用你的控件时绑定它。

最新更新