WPF中XAML与后置代码设置DataContext的差异及示例报错原因
两个示例的核心差异及示例2的问题原因
1. 示例1运行正常的逻辑
你在后置代码的构造函数里执行完InitializeComponent()之后才设置DataContext = this,这里的this指向当前正在显示的MainWindow实例:
InitializeComponent()已经加载了XAML中定义的Title="MainWindow"Height="450"Width="800"这些属性,所有属性都已有有效值- 绑定直接读取当前窗口的属性,自然能拿到正常数值
2. 示例2报错、值为NaN的两个核心原因
(1)无限递归实例化导致编译/运行错误
你在MainWindow的XAML里写了<local:MainWindow/>作为DataContext,等于触发了逻辑死循环:
- 运行程序创建第一个MainWindow实例时,会先解析XAML内容
- 解析到
<Window.DataContext>节点时,需要创建一个新的local:MainWindow实例 - 新的MainWindow实例又会解析自己的XAML,再次遇到
<local:MainWindow/>,继续创建更新的实例,无限递归下去,XAML编译器会直接检测到循环引用报错,就算编译通过运行也会触发栈溢出。
(2)即便忽略递归,数值也不对
就算递归问题被规避,你绑定的也是全新创建的另一个MainWindow实例,不是当前显示的窗口:
- WPF的
Width、Height属性在窗口未完成布局渲染时,默认值就是NaN,只有显式赋值或者布局完成后才会有有效值 - 你新创建的这个MainWindow实例根本没有显示也没有走完整的初始化流程,拿到
NaN是正常现象。
正确的XAML设置DataContext方式(无需后置代码赋值)
如果不想在后置代码里写DataContext = this,可以用RelativeSource指定绑定到当前窗口本身,不需要额外实例化:
<Window x:Class="DemoDataContextAndItemSource.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:DemoDataContextAndItemSource" mc:Ignorable="d" DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}" Title="MainWindow" Height="450" Width="800"> <!-- 其余界面内容不变 --> </Window>
内容的提问来源于stack exchange,提问作者Tony Chen
相关产品推荐
相关产品推荐

