在 WPF 中的 XAML 中设置 DataContext
Posted
技术标签:
【中文标题】在 WPF 中的 XAML 中设置 DataContext【英文标题】:Setting DataContext in XAML in WPF 【发布时间】:2014-07-06 00:08:08 【问题描述】:我有以下代码:
MainWindow.xaml
<Window x:Class="SampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="Binding Employee">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="ID:"/>
<Label Grid.Row="1" Grid.Column="0" Content="Name:"/>
<TextBox Grid.Column="1" Grid.Row="0" Margin="3" Text="Binding EmpID" />
<TextBox Grid.Column="1" Grid.Row="1" Margin="3" Text="Binding EmpName" />
</Grid>
</Window>
Employee.cs
namespace SampleApplication
public class Employee
public Employee()
EmployeeDetails employeeDetails = new EmployeeDetails();
employeeDetails.EmpID = 123;
employeeDetails.EmpName = "ABC";
public class EmployeeDetails
private int empID;
public int EmpID
get
return empID;
set
empID = value;
private string empName;
public string EmpName
get
return empName;
set
empName = value;
这是非常简单的代码,我只想将 Employee.cs 类中的 EmpID
和 EmpName
属性绑定到 MainWindow.xaml 中文本框的 Text 属性,但是当我运行时,这些文本框中没有出现任何内容代码。绑定对了吗?
【问题讨论】:
【参考方案1】:此代码将始终失败。
正如所写,它说:“在我的 DataContext 属性上查找名为“Employee”的属性,并将其设置为 DataContext 属性”。显然这是不对的。
要让您的代码按原样工作,请将您的窗口声明更改为:
<Window x:Class="SampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleApplication"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:Employee/>
</Window.DataContext>
这声明了一个新的 XAML 命名空间(本地)并将 DataContext 设置为 Employee 类的一个实例。这将导致您的绑定显示默认数据(来自您的构造函数)。
但是,这不太可能是您真正想要的。相反,您应该有一个新类(称为 MainViewModel),然后绑定到 Employee
属性,如下所示:
public class MainViewModel
public Employee MyEmployee get; set; //In reality this should utilize INotifyPropertyChanged!
现在您的 XAML 变为:
<Window x:Class="SampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleApplication"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
...
<TextBox Grid.Column="1" Grid.Row="0" Margin="3" Text="Binding MyEmployee.EmpID" />
<TextBox Grid.Column="1" Grid.Row="1" Margin="3" Text="Binding MyEmployee.EmpName" />
现在您可以添加其他属性(其他类型、名称)等。更多信息,请参阅Implementing the Model-View-ViewModel Pattern
【讨论】:
即使现在文本框也没有被填充。 @nkp,您检查过 System.Data 异常吗?他们应该指导您找出任何错别字。 在未添加程序集的情况下,我尚未成功绑定到 XAML 中的视图模型。只是为了提高认识。xmlns:local="clr-namespace:SampleApplication;assembly=SampleApplication"
@MistaGoustan 是的,您总是需要使用 XMLNS 来引用您的视图模型类型
我的项目位于共享文件夹中,并且出现类似错误【参考方案2】:
首先,您应该在 Employee
类中创建包含员工详细信息的属性:
public class Employee
public Employee()
EmployeeDetails = new EmployeeDetails();
EmployeeDetails.EmpID = 123;
EmployeeDetails.EmpName = "ABC";
public EmployeeDetails EmployeeDetails get; set;
如果您不这样做,您将在 Employee
构造函数中创建对象实例,并且您将失去对它的引用。
在 XAML 中,您应该创建 Employee
类的实例,然后您可以将其分配给 DataContext
。
您的 XAML 应如下所示:
<Window x:Class="SampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:SampleApplication"
>
<Window.Resources>
<local:Employee x:Key="Employee" />
</Window.Resources>
<Grid DataContext="StaticResource Employee">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="ID:"/>
<Label Grid.Row="1" Grid.Column="0" Content="Name:"/>
<TextBox Grid.Column="1" Grid.Row="0" Margin="3" Text="Binding EmployeeDetails.EmpID" />
<TextBox Grid.Column="1" Grid.Row="1" Margin="3" Text="Binding EmployeeDetails.EmpName" />
</Grid>
</Window>
现在,在您使用员工详细信息创建属性后,您应该使用此属性进行绑定:
Text="Binding EmployeeDetails.EmpID"
【讨论】:
【参考方案3】:这里有几个问题。
-
您不能将DataContext 分配为
DataContext="Binding Employee"
,因为它是一个不能分配为字符串的复杂对象。所以你必须使用<Window.DataContext></Window.DataContext>
语法。
您将表示数据上下文对象的类分配给视图,而不是单个属性,因此Binding Employee
在此处无效,您只需指定一个对象。
现在,当您使用如下有效语法分配数据上下文时
<Window.DataContext> <local:Employee/> </Window.DataContext>
知道您正在创建 Employee 类的新实例并将其分配为数据上下文对象。您可能在默认构造函数中没有任何内容,因此不会显示任何内容。但是,您如何在文件隐藏代码中对其进行管理?您已经对 DataContext 进行了类型转换。
private void my_button_Click(object sender, RoutedEventArgs e)
Employee e = (Employee) DataContext;
第二种方法是在文件本身的代码中分配数据上下文。这样做的好处是您的文件背后的代码已经知道它并且可以使用它。
public partial class MainWindow : Window
Employee employee = new Employee();
public MainWindow()
InitializeComponent();
DataContext = employee;
【讨论】:
以上是关于在 WPF 中的 XAML 中设置 DataContext的主要内容,如果未能解决你的问题,请参考以下文章
WPF - 为啥在 XAML 中设置 Binding BindableObject.Text 时 SetProperty() 不触发 CanExecute?
在 XAML 中设置 WPF OxyPlot PlotViews 的样式
使用 MvvmCross 时如何在 WPF App.xaml 中设置资源? (MaterialDesignInXamlToolkit)