【问题标题】:Setting DataContext in XAML in WPF在 WPF 中的 XAML 中设置 DataContext
【发布时间】: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 类中的 EmpIDEmpName 属性绑定到 MainWindow.xaml 中文本框的 Text 属性,但是当我运行时,这些文本框中没有出现任何内容代码。绑定对了吗?

【问题讨论】:

    标签: c# wpf xaml


    【解决方案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】:

      这里有几个问题。

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-19
        • 1970-01-01
        相关资源
        最近更新 更多