在WPF中的XAML中设置DataContext

53 c# wpf xaml

我有以下代码:

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>
Run Code Online (Sandbox Code Playgroud)

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是非常简单的代码,我只想将Employee.cs类中的EmpIDEmpName属性绑定到MainWindow.xaml中Textbox的Text属性,但是当我运行代码时,我的这些文本框中没有出现任何内容.绑定是对的吗?

Bra*_*NET 104

此代码将始终失败.

如上所述,它说:"在我的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>
Run Code Online (Sandbox Code Playgroud)

这声明了一个新的XAML命名空间(本地),并将DataContext设置为Employee类的实例.这将导致绑定显示默认数据(来自构造函数).

但是,这实际上并不是你想要的.相反,你应该有一个新类(称之为MainViewModel),Employee然后绑定一个属性,如下所示:

public class MainViewModel
{
   public Employee MyEmployee { get; set; } //In reality this should utilize INotifyPropertyChanged!
}
Run Code Online (Sandbox Code Playgroud)

现在您的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}" />
Run Code Online (Sandbox Code Playgroud)

现在您可以添加其他属性(其他类型,名称)等.有关更多信息,请参阅实现Model-View-ViewModel模式

  • 应该注意的是,DataContext 仅在窗口类的构造函数中调用“InitializeComponent()”之后设置(代码隐藏)。以防万一有人有一些依赖于要设置的数据上下文的初始化代码。 (2认同)

kma*_*zek 18

首先,您应该在Employee类中创建具有员工详细信息的属性:

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

    public EmployeeDetails EmployeeDetails { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如果不这样做,您将在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>
Run Code Online (Sandbox Code Playgroud)

现在,在使用员工详细信息创建属性后,您应该使用此属性进行绑定:

Text="{Binding EmployeeDetails.EmpID}"
Run Code Online (Sandbox Code Playgroud)


zar*_*zar 9

这里有几个问题。

  1. 您不能分配 DataContextDataContext="{Binding Employee}"因为它是一个复杂的对象,不能分配为字符串。所以你必须使用<Window.DataContext></Window.DataContext>语法。
  2. 您将表示数据上下文对象的类分配给视图,而不是单个属性,因此{Binding Employee}此处无效,您只需指定一个对象即可。
  3. 现在,当您使用如下所示的有效语法分配数据上下文时
<Window.DataContext>
    <local:Employee/>
</Window.DataContext>
Run Code Online (Sandbox Code Playgroud)

知道您正在创建Employee 类的新实例并将其指定为数据上下文对象。默认构造函数中可能没有任何内容,因此不会显示任何内容。但是那么如何在代码隐藏文件中管理它呢?您已经对 DataContext 进行了类型转换。

private void my_button_Click(object sender, RoutedEventArgs e)
{
    Employee e = (Employee) DataContext;
}
Run Code Online (Sandbox Code Playgroud)
  1. 第二种方法是在文件背后的代码中分配数据上下文。这样做的好处是您的文件背后的代码已经知道它并且可以使用它。

     public partial class MainWindow : Window
     {
         Employee employee = new Employee();
    
         public MainWindow()
         {
             InitializeComponent();    
             DataContext = employee;
         }
     }
    
    Run Code Online (Sandbox Code Playgroud)