web-dev-qa-db-ja.com

WPFのXAMLでDataContextを設定する

私は次のコードを持っています:

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のTextboxesのTextプロパティにバインドしたいだけですが、これらのテキストボックスには何も表示されません。コードを実行します。バインディングは正しいですか?

51
user1556433

このコードは常に失敗します。

書かれているように、「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クラスのインスタンスに設定されます。これにより、バインディングにデフォルトデータ(コンストラクターから)が表示されます。

ただし、これが実際に必要なことはほとんどありません。代わりに、次のようにバインドするEmployeeプロパティを持つ新しいクラス(MainViewModelと呼びます)が必要です。

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}" />

これで、他のプロパティ(他のタイプ、名前)などを追加できます。詳細については、「 Model-View-ViewModelパターンの実装 」を参照してください。

98
BradleyDotNET

まず、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}"
16
kmatyaszek