我对 DataContext 感到进退两难。让我们检查以下 XAML:
<Window xmlns:my="clr-namespace:MyNamespace.Controls"
... >
...
<my:MyControl Name="{Binding Prop1}" Value="{Binding Prop2}" />
</Window>
显然,Window 的代码隐藏包含如下内容:
DataContext = someViewModel;
作者的意图很明确——他想绑定(bind)MyControl
的 Name
和 Value
至 Window
的 DataContext
的 Prop1
和 Prop2
.这当然会奏效。除非。 (戏剧性的停顿)
除非MyControl
是复合 UserControl
,它还想利用绑定(bind)的短符号并设置其 DataContext
到它自己的 View 模型。因为那样就会清楚,Window's
中的绑定(bind)XAML 实际上绑定(bind)到 MyControl
的 DataContext
(以前继承自 Window
的一个)现在它们将停止工作(或者更糟的是,如果 MyControl
的 View 模型实际上包含名为 Prop1
和 Prop2
的属性,它们将继续工作 1 ).
在这种特殊情况下,解决方案是在 Window
中绑定(bind)的代码明确:
<Window x:Name="rootControl"
xmlns:my="clr-namespace:MyNamespace.Controls"
... >
...
<my:MyControl Name="{Binding ElementName=rootControl, Path=DataContext.Prop1}"
Value="{Binding ElementName=rootControl, Path=DataContext.Prop2}" />
</Window>
TL;DR 如果我们使用简短的绑定(bind)符号(当绑定(bind)到 DataContext
时),我们可能会遇到由于绑定(bind)突然指向错误的 DataContext
而导致的错误。 .
我的问题是:如何毫无风险地使用短绑定(bind)符号,我会绑定(bind)到错误的 DataContext
?当然,我可能会使用缩写当我确定时,我将使用继承的DataContext
。和长符号 当我确定 时,该控件将修改其 DataContext
.但是,“我确定”只会在第一个错误出现之前起作用,这将花费另一个小时的调试时间。
也许我没有遵循一些 MVVM 规则?例如。例如DataContext
应该只在顶层设置一次并且所有复合控件都应该绑定(bind)到其他东西?
1 事实上,我已经经历过了。
Window
的 DataContext
包含一个名为(比如说)Prop
的属性并且控件替换了它的 DataContext
有一个类,其中还包含一个属性 Prop
一切正常。当我尝试(无意识地)使用具有不匹配属性名称的相同模式时出现问题。
根据要求:
MyControl 的代码片段:
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
// Using a DependencyProperty as the backing store for Name. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(MyControl), new PropertyMetadata(null));
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(int), typeof(MyControl), new PropertyMetadata(0));
窗口的 View 模型:
public class WindowViewmodel : INotifyPropertyChanged
{
// (...)
public string Prop1
{
get
{
return prop1;
}
set
{
prop1 = value;
OnPropertyChanged("Prop1");
}
}
public int Prop2
{
get
{
return prop2;
}
set
{
prop2 = value;
OnPropertyChanged("Prop2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
现在假设,在更改 Name
时和 Value
依赖属性,MyControl
生成一些 View 模型并执行代码:
model = new MyControlViewModel(Name, Value);
this.DataContext = model;
和内部MyControl
控件绑定(bind)到此 DataContext。
从现在开始,原创Name
和 Value
绑定(bind)将不再有效。
最佳答案
Unless MyControl is a composite UserControl, which also wants to take advantage of short notation of bindings and sets its DataContext to its own viewmodel.
这就是我停止阅读的地方。恕我直言,这是一个 MVVM 反模式。
这样做的原因是双重的。首先,你搞砸了任何使用控件的人。 “嘿,”你说,“你不能把你那臭臭的虚拟机绑定(bind)到我漂亮的用户界面上。你必须使用我的自定义虚拟机!”但是,如果您的 VM 难以使用,缺少整个应用程序所需的逻辑或功能怎么办?如果要使用您的 UI,我们必须在您的 VM 之间来回转换我们的 VM/模型,会发生什么情况?屁股痛。
其次是您的自定义控件是 UI。它的逻辑是UI逻辑,所以没有必要使用view model。最好在控件上公开 DependencyProperties 并根据需要更新 UI。这样任何人都可以绑定(bind)到您的 UI 并将其用于任何模型或 View 模型。
关于c# - 使用(DataContext)还是不使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21093396/