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

时间:2011-08-29 20:15:23

标签: wpf data-binding

问题是我总是希望将控件绑定到DataContext属性。因为我不喜欢在Binding表达式中指定Source。但是,我不想显式绑定我的控件的DataContext属性,而是使用另一个指定的和自描述的属性,如Items或Plugins或控制的目的。 现在,只要设置了真正确定控件上下文的自描述属性,我就需要一种方法来设置DataContext属性。此外,我希望DataContext始终与此属性相同。如何做到这一点?

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

这是我的PropertyMetadata,在回调中带有断点:

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

这就是callstack(行末有注释):

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的新手,所以我可以把它弄错。

2 个答案:

答案 0 :(得分:1)

根据latest question中的答案,DataContext是您的Bindings将用作其数据源的对象。

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

示例 - 而不是像以下那样指定Binding:

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

你可以使用

{Binding Path=PropertyName}

因为容器DataContext属性设置为ControlName的实例(仅当您指定DataContext = this时才会出现这种情况,不是 {{1}因为这只会将它设置为自己并且毫无意义。)

现在,对于DataContext = this.DataContextPage个对象,Window可以是注册PropertyName实例,也可以是提出的库存标准DependencyProperty Property事件,用于通知XAML中的子项已更改属性,并根据需要自行更新。

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

您是否可以使用任何来源更新您的帖子,以便我们为您查看?


原始答案:

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

DependencyProperty

这样就无需在Binding中设置Source和RelativeSource属性,同时仍允许您直接绑定到页面属性。

示例:

this.DataContext = this;

然后在你的XAML中:

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;
    }
}

答案 1 :(得分:1)

我真的没有理由创建一个替代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.DataContext,请对User为{{{1}}的初始化进行某种验证检查{1}}对象。不要创建某种人们需要记住的自定义属性,以便在他们想要使用您的控件时随时绑定。