WPF之DataContext(转)

有时候不是你不够聪明,而是别人教给你的东西太烂!相信自己!
这是我认为,目前网络上对“DataContext”解释最好的一篇文章,跟大家分享。

What is this “DataContext” you speak of?

I frequently see new WPF users confused about what the DataContext is, and how it is used. Hopefully, this can help clarify what the DataContext is, and how it is used.

What is the DataContext?

In WPF, there are two layers to an application: the UI layer and the Data layer.

The Data layer for an application starts out as null, and you can set it using the DataContext property. All UI objects will inherit their DataContext from their parent unless you specify otherwise.

When using the Model-View-ViewModel (MVVM) Design Pattern, the DataContext (Data Layer) is your application, while UI objects, like Buttons, Labels, DataGrids, and even Windows, are all just user-friendly items that allow a user to easily interact with the DataContext, which is your actual application and is typically comprised of ViewModels and Models.

How is it used

Whenever you do a basic binding in WPF, you are binding to the DataContext.

For example, when you write

<Label Name="myLabel" Content="{Binding Path=Name}" />

you are binding to myLabel.DataContext.Name, and not to myLabel.Name.

Other binding properties, such as ElementName or RelativeSource, can be used to tell the binding to lookup the property in something other than the current DataContext.

An Example

Lets start with a regular Window. Without setting the DataContext, the window still displays but there is no data behind it.

<Window x:Name="MyWindow" ...>
   ...
</Window>

Now suppose we set the DataContext to an object of type ClassA in the code-behind when this Window initializes:

public partial class MyWindow: Window
{
    public MyWindow()
    {
       InitializeComponent();
       this.DataContext = new ClassA();
    }
}

Now the data layer behind that the Window is an object of type ClassA.

If ClassA has a property called Name, I could add a Label to the window and bind it to Name property of the DataContext, and whatever value is stored in ClassA.Name would get displayed.

<Window x:Name="MyWindow" ...>
   <Label Content="{Binding Name}" />
</Window>

Now, suppose ClassA has a property called ClassB, and both classes have a property called Name. Here is a block of XAML which illustrates how the DataContext works. It also includes an example of how a control would refer to a property not in its own DataContext.

<!-- DataContext set to ClassA in initialization code -->
<Window x:Name="MyWindow">
 
    <!-- DataContext here is not specified, so it's inherited
         from its parent's DataContext, which is ClassA -->
    <StackPanel>
 
        <!-- DataContext inherited from parent, which is
             ClassA, so this will display ClassA.Name -->
        <Label Content="{Binding Name}" />
 
         <!-- DataContext is still ClassA, however we are
              setting it to ClassA.ClassB with a binding -->
        <StackPanel DataContext="{Binding ClassB}">
 
            <!-- DataContext inherited from parent, which is
                 ClassB, so this will display ClassB.Name -->
            <Label Content="{Binding Name}" />
 
            <!-- DataContext is still ClassB, but we are
                 binding to the Window's DataContext.Name,
                 which is ClassA.Name -->
            <Label Content="{Binding
                       ElementName=MyWindow,
                       Path=DataContext.Name}" />
        </StackPanel>
 
        <!-- We've left the StackPanel with its DataContext
             bound to ClassB, so this Label's DataContext
             is ClassA (inherited from parent StackPanel),
             and we are binding to ClassA.ClassB.Name -->
        <Label Content="{Binding ClassB.Name}" />
    </StackPanel>
</Window>

As you can see, all the basic bindings look for their value in the data layer (DataContext) of the UI object

Summary

So to summarize, WPF applications have two layers: the UI layer and the Data layer. The data layer for an application starts out as null, and can be set using the DataContext property. UI objects without a DataContext set will inherit their data layer from their parent object. Bindings are used to look up values in the data layer, and display them in the UI layer.

When using the MVVM design pattern, the data layer is your application, while the UI layer just provides a user-friendly way to access the Data layer.

What is this “DataContext” you speak of?

I frequently see new WPF users confused about what the DataContext is, and how it is used. Hopefully, this can help clarify what the DataContext is, and how it is used.

What is the DataContext?

In WPF, there are two layers to an application: the UI layer and the Data layer.

The Data layer for an application starts out as null, and you can set it using the DataContext property. All UI objects will inherit their DataContext from their parent unless you specify otherwise.

When using the Model-View-ViewModel (MVVM) Design Pattern, the DataContext (Data Layer) is your application, while UI objects, like Buttons, Labels, DataGrids, and even Windows, are all just user-friendly items that allow a user to easily interact with the DataContext, which is your actual application and is typically comprised of ViewModels and Models.

How is it used

Whenever you do a basic binding in WPF, you are binding to the DataContext.

For example, when you write

<Label Name="myLabel" Content="{Binding Path=Name}" />

you are binding to myLabel.DataContext.Name, and not to myLabel.Name.

Other binding properties, such as ElementName or RelativeSource, can be used to tell the binding to lookup the property in something other than the current DataContext.

An Example

Lets start with a regular Window. Without setting the DataContext, the window still displays but there is no data behind it.

<Window x:Name="MyWindow" ...>
   ...
</Window>

Now suppose we set the DataContext to an object of type ClassA in the code-behind when this Window initializes:

public partial class MyWindow: Window
{
    public MyWindow()
    {
       InitializeComponent();
       this.DataContext = new ClassA();
    }
}

Now the data layer behind that the Window is an object of type ClassA.

If ClassA has a property called Name, I could add a Label to the window and bind it to Name property of the DataContext, and whatever value is stored in ClassA.Name would get displayed.

<Window x:Name="MyWindow" ...>
   <Label Content="{Binding Name}" />
</Window>

Now, suppose ClassA has a property called ClassB, and both classes have a property called Name. Here is a block of XAML which illustrates how the DataContext works. It also includes an example of how a control would refer to a property not in its own DataContext.

<!-- DataContext set to ClassA in initialization code -->
<Window x:Name="MyWindow">
 
    <!-- DataContext here is not specified, so it's inherited
         from its parent's DataContext, which is ClassA -->
    <StackPanel>
 
        <!-- DataContext inherited from parent, which is
             ClassA, so this will display ClassA.Name -->
        <Label Content="{Binding Name}" />
 
         <!-- DataContext is still ClassA, however we are
              setting it to ClassA.ClassB with a binding -->
        <StackPanel DataContext="{Binding ClassB}">
 
            <!-- DataContext inherited from parent, which is
                 ClassB, so this will display ClassB.Name -->
            <Label Content="{Binding Name}" />
 
            <!-- DataContext is still ClassB, but we are
                 binding to the Window's DataContext.Name,
                 which is ClassA.Name -->
            <Label Content="{Binding
                       ElementName=MyWindow,
                       Path=DataContext.Name}" />
        </StackPanel>
 
        <!-- We've left the StackPanel with its DataContext
             bound to ClassB, so this Label's DataContext
             is ClassA (inherited from parent StackPanel),
             and we are binding to ClassA.ClassB.Name -->
        <Label Content="{Binding ClassB.Name}" />
    </StackPanel>
</Window>

As you can see, all the basic bindings look for their value in the data layer (DataContext) of the UI object

Summary

So to summarize, WPF applications have two layers: the UI layer and the Data layer. The data layer for an application starts out as null, and can be set using the DataContext property. UI objects without a DataContext set will inherit their data layer from their parent object. Bindings are used to look up values in the data layer, and display them in the UI layer.

When using the MVVM design pattern, the data layer is your application, while the UI layer just provides a user-friendly way to access the Data layer.

WPF之DataContext(转)的更多相关文章

  1. WPF之DataContext

    1. 继承属性: DataContext is a property on FrameworkElement (base class for all WPF Controls) and is impl ...

  2. [WPF] How to bind to data when the datacontext is not inherited

    原文:[WPF] How to bind to data when the datacontext is not inherited 原文地址:http://www.thomaslevesque.co ...

  3. WPF入门(1)——DataContext

    在WPF中,应用程序有两层:UI层和Data层.这里新建一个项目说明哪些是UI层,哪些是数据层. UI层很明显,就是用户看到的界面.但是数据层并不是下图所示: 上图中是UI层view的后台代码.当然, ...

  4. 【我们一起写框架】MVVM的WPF框架(二)—绑定

    MVVM的特点之一是实现数据同步,即,前台页面修改了数据,后台的数据会同步更新. 上一篇我们已经一起编写了框架的基础结构,并且实现了ViewModel反向控制Xaml窗体. 那么现在就要开始实现数据同 ...

  5. [No000012E]WPF(6/7):概念绑定

    WPF 的体系结构,标记扩展,依赖属性,逻辑树/可视化树,布局,转换等.今天,我们将讨论 WPF 最重要的一部分——绑定.WPF 带来了优秀的数据绑定方式,可以让我们绑定数据对象,这样每次对象发生更改 ...

  6. 关于WPF中ItemsControl系列控件中Item不能继承父级的DataContext的解决办法

    WPF中所有的集合类控件,子项都不能继承父级的DataContext,需要手动将绑定的数据源指向到父级控件才可以. <DataGridTemplateColumn Header="操作 ...

  7. WPF设置Window的数据上下文(DataContext)为自身

    WPF设置Window的数据上下文(DataContext)为自身的XAML: DataContext="{Binding RelativeSource={RelativeSource Se ...

  8. WPF中 ItemsSource 和DataContext不同点

    此段为原文翻译而来,原文地址 WPF 中 数据绑定 ItemSource和 DataContext的不同点: 1.DataContext 一般是一个非集合性质的对象,而ItemSource 更期望数据 ...

  9. WPF学习笔记——DataContext 与 ItemSource

    作为一个WPF新手,在ListBox控件里,我分不清 DataContext 与 ItemSource的区别. 在实践中,似乎: <ListBox x:Name="Lst" ...

随机推荐

  1. Linux常用命令手册

    Linux常用命令手册 NO 分类 PS1 命令名 用法及参数 功能注解 对应章节 1 文件管理 # ls ls -a 列出当前目录下的所有文件,包括以.头的隐含文件     文件管理 # ls ls ...

  2. ng-csv 异步数据下载

    相信很多码友遇到一个很坑的问题吧,就是使用ng-csv  的时候 lazy-load="true" 设置为true 还是 会下载0行数据 var getArray= functio ...

  3. 分享:Python中的位运算符

    按位运算符是把数字看作二进制来进行计算的.用的不太多,简单了解. 下表中变量 a 为 60,b 为 13二进制格式如下: a = 0011 1100 b = 0000 1101 a&b = 0 ...

  4. 字符串相似度-C#

    之前在做一个任务时, 需要比较字符串的相似度, 最终整理了一个出来, 以下: 1 /* 2 * Copyright (c) 2013 Thyiad 3 * Author: Thyiad 4 * Cre ...

  5. hbase优化之region合并和压缩

    HBASE操作:(一般先合并region然后再压缩) 一 .Region合并: merge_region   'regionname1','regionname2' ,'true'  --true代表 ...

  6. 浏览器输入URL到响应页面的全过程

    B/S网络架构从前端到后端都得到了简化,都基于统一的应用层协议HTTP来交互数据,HTTP协议采用无状态的短链接的通信方式,通常情况下,一次请求就完成了一次数据交互,通常也对应一个业务逻辑,然后这次通 ...

  7. dubbox系列【三】——简单的dubbox提供者+消费者示例

    1.dubbox-provider示例 在eclipse中建立maven project,名为provider-parent,包含两个maven medule:provider-api 和 provi ...

  8. CodeForces - 796A Buying A House

    思路:从m直接向两边枚举,如果当前点需要的费用小于等于k,说明一定是最近距离. AC代码 #include <cstdio> #include <cmath> #include ...

  9. HDU - 1907 John 反Nimm博弈

    思路: 注意与Nimm博弈的区别,谁拿完谁输! 先手必胜的条件: 1.  每一个小游戏都只剩一个石子了,且SG = 0. 2. 至少有一堆石子数大于1,且SG不等于0 证明:1. 你和对手都只有一种选 ...

  10. 禁掉coolie,session还能正常使用吗?

    Cookie禁用了,Session还能用吗?   Cookie与 Session,一般认为是两个独立的东西,Session采用的是在服务器端保持状态的方案,而Cookie采用的是在客户端保持状态的方案 ...