c# - 使用(DataContext)还是不使用

标签 c# wpf xaml mvvm binding

我对 DataContext 感到进退两难。让我们检查以下 XAML:

<Window xmlns:my="clr-namespace:MyNamespace.Controls"
        ... >
    ...
    <my:MyControl Name="{Binding Prop1}" Value="{Binding Prop2}" />
</Window>

显然,Window 的代码隐藏包含如下内容:

DataContext = someViewModel;

作者的意图很明确——他想绑定(bind)MyControlNameValueWindowDataContextProp1Prop2 .这当然会奏效。除非。 (戏剧性的停顿)

除非MyControl是复合 UserControl ,它还想利用绑定(bind)的短符号并设置其 DataContext到它自己的 View 模型。因为那样就会清楚,Window's 中的绑定(bind)XAML 实际上绑定(bind)到 MyControlDataContext (以前继承自 Window 的一个)现在它们将停止工作(或者更糟的是,如果 MyControl 的 View 模型实际上包含名为 Prop1Prop2 的属性,它们将继续工作 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 事实上,我已经经历过了。 WindowDataContext包含一个名为(比如说)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。

从现在开始,原创NameValue绑定(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/

相关文章:

c# - 如何从资源项目中获取图像

c# - Silverlight:来自一个用户控件的事件能否在不同的用户控件和/或包含控件上开始动画

c# - System.Windows.Data 错误 : 1 System. Windows.Data 错误:5

wpf - 将样式放在网格样式内的控件上

c# - 如何设置 UWP 元素的状态?

wpf - 如何在 XAML 中绘制一个三等分的圆?

c# - 开发 C# 报告工具 - 我应该使用 Google Analytics(分析)吗?

c# - Azure 媒体服务、具有 V3 api 的 GetLocators 和 ODataQuery

c# - 最长公共(public)子序列

c# - WPF 应用程序是否需要使用 XAML?