本文介绍了将DataContext与WPF中的另一个属性相链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

事情是我总是希望绑定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)/ *将属性设置为null。为什么??? * / 
2. [外部代码]
1. Bla-bla-bla.SearchSettings..cctor.AnonymousMethod__7(DependencyObject d,DependencyPropertyChangedEventArgs e)/ *这是断点首先命中的位置。由于数据绑定,为属性设置一个新值。 * /

那么我该怎么办?还是我想要这样做? BTW,我是WPF的新手,所以我可以把它弄错了。

解决方案

我真的没有看到理由创建一个替代 DataContext的属性



DataContext 是指控制背后的实际数据。为什么要创建一个已经存在的第二个属性?对我来说,就像说要重写控件的 IsReadOnly 属性,因此它读取 DisableEditing - 没有任何目的它。



此外,为什么要将它绑定到应用层? WPF的全部要点是将业务/应用程序逻辑与UI分开,您正在尝试的是将两者结合在一起。如果你想要这个行为,可以使用WinForms。



如果你想确定你的 UserControl 只用于一个 User DataContext,使用 DataTemplate

 < DataTemplate DataType ={x:Type local:User}> 
< local:MyUserControl /> <! - DataContext将是User - >
< / DataTemplate>

<! - 这将显示一个User对象,但是由于DataTemplate它将
绘制它使用您的UserControl而不是默认的User.ToString() - >
< ContentControl Content ={Binding CurrentUser}/>

如果您真的想确保您的 UserControl 只收到用户对象作为 DataContext ,对初始化进行某种验证检查 this.DataContext 是一个用户对象。不要创建某种自定义属性,人们需要记住在任何时候想要使用你的控件来绑定。


The thing is I always want to bind controls against DataContext property. Because I don't like specifying Source in Binding expression. However, I do not want to bind DataContext property of my controls explicitly, but use another designated and self-descriptive properties, like Items or Plugins or whatever the purpose of control is.Now, I need a way to set DataContext property whenever that self-descriptive property truly determining the context of a control is set. Moreover, I want DataContext to always same as this property. How this can be done?

I tried specifying PropertyMetadata with callback that would set DataContext on newly received value. It doesn't work. Firstly, because this callback isn't being called for default value of a property. And secondly, and that is most interesting, I observed very strange behavior. Let me explain this using a callstack:

This is my PropertyMetadata with breakpoint in the callback:

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

And this is the callstack (there are comments at the ends of the lines):

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. */

So, how do I do it? Or should I want to do it at all? BTW, I am new to WPF, so I could get it all wrong.

解决方案

I really don't see a reason to create a property that substitutes for the DataContext

The purpose of the DataContext is to refer to the actual data behind your control. Why would you create a 2nd property for one that already exists? To me that's like saying you want to rewrite the IsReadOnly property of a control so it reads DisableEditing - there's no purpose for it.

And furthermore, why would you want tie it to your application layer? The whole point of WPF is to separate business/application logic from the UI, and what you are trying to do is tie the two together. Use WinForms if you want that behavior.

If you want to be sure your UserControl is only used with a User DataContext, use a 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}" /> 

If you really want to ensure that your UserControl only receives a User object as the DataContext, do some kind of validation check on initialization that this.DataContext is a User object. Don't create some kind of custom property that people need to remember to bind anytime they want to use your control.

这篇关于将DataContext与WPF中的另一个属性相链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 11:42