问题是我总是希望将控件绑定到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的新手,所以我可以把它弄错。
答案 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.DataContext
或Page
个对象,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}}对象。不要创建某种人们需要记住的自定义属性,以便在他们想要使用您的控件时随时绑定。