简体   繁体   English

在 WPF 中的 XAML 中设置 DataContext

[英]Setting DataContext in XAML in WPF

I have following code:我有以下代码:

MainWindow.xaml主窗口.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员工.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;
            }
        }
    }
}

This is very simple code and I just want to bind the EmpID and EmpName properties in my Employee.cs class to Text properties of Textboxes in MainWindow.xaml but nothing is appearing in my these textboxes when I am running the code.这是非常简单的代码,我只想将 Employee.cs 类中的EmpIDEmpName属性绑定到 MainWindow.xaml 中文本框的文本属性,但是当我运行代码时,这些文本框中没有任何内容。 Is the binding right?绑定对吗?

This code will always fail.此代码将始终失败。

As written, it says: "Look for a property named "Employee" on my DataContext property, and set it to the DataContext property".正如所写,它说:“在我的 DataContext 属性上查找名为“Employee”的属性,并将其设置为 DataContext 属性”。 Clearly that isn't right.显然这是不对的。

To get your code to work, as is, change your window declaration to:为了让您的代码正常工作,请将您的窗口声明更改为:

<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>

This declares a new XAML namespace (local) and sets the DataContext to an instance of the Employee class.这将声明一个新的 XAML 命名空间(本地)并将 DataContext 设置为 Employee 类的实例。 This will cause your bindings to display the default data (from your constructor).这将导致您的绑定显示默认数据(来自您的构造函数)。

However, it is highly unlikely this is actually what you want.但是,这实际上不太可能是您想要的。 Instead, you should have a new class (call it MainViewModel) with an Employee property that you then bind to, like this:相反,您应该有一个带有Employee属性的新类(称为 MainViewModel),然后绑定到该类,如下所示:

public class MainViewModel
{
   public Employee MyEmployee { get; set; } //In reality this should utilize INotifyPropertyChanged!
}

Now your XAML becomes:现在您的 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}" />

Now you can add other properties (of other types, names), etc. For more information, see Implementing the Model-View-ViewModel Pattern现在您可以添加其他属性(其他类型、名称)等。有关更多信息,请参阅实现模型-视图-视图模型模式

First of all you should create property with employee details in the Employee class:首先,您应该在Employee类中创建包含员工详细信息的属性:

public class Employee
{
    public Employee()
    {
        EmployeeDetails = new EmployeeDetails();
        EmployeeDetails.EmpID = 123;
        EmployeeDetails.EmpName = "ABC";
    }

    public EmployeeDetails EmployeeDetails { get; set; }
}

If you don't do that, you will create instance of object in Employee constructor and you lose reference to it.如果您不这样做,您将在Employee构造函数中创建对象的实例,并且您将失去对它的引用。

In the XAML you should create instance of Employee class, and after that you can assign it to DataContext .在 XAML 中,您应该创建Employee类的实例,然后您可以将其分配给DataContext

Your XAML should look like this:您的 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>

Now, after you created property with employee details you should binding by using this property:现在,在使用员工详细信息创建属性后,您应该使用此属性进行绑定:

Text="{Binding EmployeeDetails.EmpID}"

There are several issues here.这里有几个问题。

  1. You can't assign DataContext as DataContext="{Binding Employee}" because it's a complex object which can't be assigned as string.您不能将 DataContext 分配为DataContext="{Binding Employee}"因为它是一个不能分配为字符串的复杂对象。 So you have to use <Window.DataContext></Window.DataContext> syntax.所以你必须使用<Window.DataContext></Window.DataContext>语法。
  2. You assign the class that represents the data context object to the view, not an individual property so {Binding Employee} is invalid here, you just have to specify an object.您将表示数据上下文对象的类分配给视图,而不是单个属性,因此{Binding Employee}在这里无效,您只需要指定一个对象。
  3. Now when you assign data context using valid syntax like below现在,当您使用如下有效语法分配数据上下文时
 <Window.DataContext> <local:Employee/> </Window.DataContext>

know that you are creating a new instance of the Employee class and assigning it as the data context object.知道您正在创建Employee 类的新实例并将其分配为数据上下文对象。 You may well have nothing in default constructor so nothing will show up.您可能在默认构造函数中没有任何内容,因此不会显示任何内容。 But then how do you manage it in code behind file?但是你如何在代码隐藏文件中管理它? You have typecast the DataContext.您已经对 DataContext 进行了类型转换。

    private void my_button_Click(object sender, RoutedEventArgs e)
    {
        Employee e = (Employee) DataContext;
    }
  1. A second way is to assign the data context in the code behind file itself.第二种方法是在文件本身的代码背后分配数据上下文。 The advantage then is your code behind file already knows it and can work with it.优点是您的文件背后的代码已经知道它并且可以使用它。

     public partial class MainWindow : Window { Employee employee = new Employee(); public MainWindow() { InitializeComponent(); DataContext = employee; } }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM