【问题标题】:Confused in DataContext in WPF对 WPF 中的 DataContext 感到困惑
【发布时间】:2014-07-29 06:50:36
【问题描述】:

我是 WPF 和 MVMM 架构的初学者。 VI遇到了许多解释WPF MVMM架构中DataContext依赖属性的链接,

即 view.DataContext = new ViewModels.MainViewModel();

但他们总是让我感到困惑。虽然我对这个 DataContext 有一些基本的想法,比如它用于表示我们在 xaml 文件中需要谁的对象,但是当博客谈论 dataContext 的树结构继承时,我感到困惑。谁能帮我举一些非常简单明了的例子来说明这个 DataContext 层次结构是如何工作的?

提前致谢。

【问题讨论】:

标签: wpf mvvm datacontext


【解决方案1】:

DataContext 属性指定Data Binding 的默认来源。考虑以下示例:

<TextBox Text="{Binding MyProperty}" />

Binding 的意思是:从DataContext 中的任何对象中获取MyProperty 的值,将其转换为字符串并放入TextBox。因此,如果我们将TextBoxDataContext 设置为以下类的对象:

public class Example {
     int MyProperty { get { return 3; } }
}

然后,TextBoxText 将设置为 3

Inherit是什么意思?考虑一个稍微复杂一点的例子:

<Window Name="MainWindow">
     <StackPanel>
          <TextBox Text="{Binding MyProperty}" />
          ...etc

如果我们的屏幕上有 10 个或更多 TextBox 元素,那么将 DataContext 分配给每个 TextBox 将是一项毫无意义的工作。为了缓解这个问题,WPF 的实现者决定在我们的例子中将DataContext 设置在MainWindow 上也会将其应用于Window 的所有内部(所有子元素,所有嵌套元素)直到DataContext 属性被覆盖(即我们设置TextBoxDataContext,然后TextBox 及其所有子级也将收到此DataContext)。

如果您想看到这种行为的实际效果,同样适用于FontSize 属性,请尝试将WindowFontSize 设置为48,看看那里的所有文本会发生什么变化!

【讨论】:

    【解决方案2】:

    Datacontext 属性是 View 的所有绑定的默认来源。 在 MVVM 中,Datacontext 用于将 ViewModel 链接到 View。

    由于Datacontext属性是一个依赖属性,如果不在控件中定义它,它会继承自他的父亲等等。

    这是 MVVM 实现的示例

    所有 ViewModel 类的父级(在所有 ViewModel 中实现 INotifyPropertyChanged):

    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    注意:INotifyPropertyChanged 允许您的 ViewModel 通知 View 更改(用于绑定)。

    假设我希望将 MainWindows(视图)链接到 ViewModel:

        public MainWindow()
        {
            InitializeComponent();
    
            MainViewModel mainViewModel = new MainViewModel(this);
            this.DataContext = mainViewModel;
        }
    

    对于 ViewModel :

    class MainViewModel : ViewModelBase
    {
        #region fields
    
        private MainWindow mainWindow;
    
        private string message = "Hello world !";
    
        #endregion
    
    
        #region properties
    
        public MainWindow MainWindow
        {
            get
            {
                return this.mainWindow;
            }
        }
    
        public string Message
        {
            get
            {
                return message;
            }
            set
            {
                this.message = value; OnPropertyChanged("Message");
            }
        }
    
        // ...
    
        #endregion
    
        public MainViewModel(MainWindow mainWindow)
        {
            this.mainWindow = mainWindow;
        }
    }
    

    所以现在如果我想在我的视图(主窗口)中绑定 MainViewModel 的一个属性,我只需要在我的 ViewModel 中有一个公共属性并在我的 XAML 中创建一个绑定。我不必指定源,因为 DataContext 是默认源。

    所以我可以添加 MainWindow.xaml :

    <TextBox Text="{Binding Message}" />
    

    【讨论】:

    • 这就是我困惑的地方。 1 个答案(来自 Antoine)在后端显示继承,另一个(来自 Bas Brekelmans)在 UI 中显示。再次在同一页面上。
    猜你喜欢
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 2012-07-22
    • 2013-05-13
    • 2020-04-16
    • 2023-03-08
    • 2019-08-04
    相关资源
    最近更新 更多