7

これは WPF であるため、大量のコードのように見えるかもしれませんが、心配しないでください。問題は非常に単純です。

次の XAML があります。

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:hax="clr-namespace:hax" x:Class="hax.MainWindow"
    x:Name="Window" Title="Haxalot" Width="640" Height="280">

    <Grid x:Name="LayoutRoot">
        <ListView ItemsSource="{Binding AllRoles}" Name="Hello">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name"
                       DisplayMemberBinding="{Binding Path=FullName}"/>
                    <GridViewColumn Header="Role"
                       DisplayMemberBinding="{Binding Path=RoleDescription}"/>
                </GridView>
            </ListView.View>
        </ListView> 
    </Grid>
</Window>

私はこのコードビハインドを持っています:

using System.Collections.ObjectModel;
using System.Windows;

namespace hax
{

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public ObservableCollection<Role> AllRoles { get { return m_AllRoles; } set { m_AllRoles = value; } }
        private ObservableCollection<Role> m_AllRoles = new ObservableCollection<Role>();

        public MainWindow()
        {
            this.InitializeComponent();

            AllRoles.Add(new Role("John", "Manager"));
            AllRoles.Add(new Role("Anne", "Trainee"));
            // Hello.ItemsSource = AllRoles; // NOTE THIS ONE!
        }
    }
}

Hello.ItemSource = AllRolesステートメントをコメントアウトしたままにしておくと、グリッドには何も表示されません。元に戻すと、正しいものが表示されます。どうしてこれなの?

4

2 に答える 2

16

これ:

<ListView ItemsSource="{Binding AllRoles}" Name="Hello">

ItemsSourceは「プロパティにバインドする」ことを意味しますthis.DataContext.AllRoles。ここthisで、 は現在の要素です。

Hello.ItemsSource = AllRoles;

は、「いっぱいのロールにバインドする」という意味ItemsSourceObservableCollection<T>、本来やろうとしていたことを直接実行します。

xaml でこれを行う方法はいくつかあります。ここに1つあります:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
        var allRoles = new ObservableCollection<Role>()
        allRoles.Add(new Role("John", "Manager"));
        allRoles.Add(new Role("Anne", "Trainee"));
        this.DataContext = allRoles;
    }
}

そしてxamlで

<ListView ItemsSource="{Binding}" Name="Hello">

または、代わりに、 AllRoles をウィンドウのパブリック プロパティにすることもできます

public partial class MainWindow : Window
{
    public ObservableCollection<Role> AllRoles {get;private set;}
    public MainWindow()
    {
        this.InitializeComponent();
        var allRoles = new ObservableCollection<Role>()
        allRoles.Add(new Role("John", "Manager"));
        allRoles.Add(new Role("Anne", "Trainee"));
        this.AllRoles = allRoles;
    }
}

次に、RelativeSource を使用して、Binding に論理ツリーを上って Window に移動するように指示します。

<ListView 
  ItemsSource="{Binding AllRoles, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 
  Name="Hello">

これは、「ウィンドウが見つかるまで私の先祖を見てから、AllRoles というウィンドウのパブリック プロパティを探してください」という意味です。

しかし、これを行う最善の方法は、コードビハインドを完全にスキップして、MVVM パターンを使用することです。 MVVM パターンに直接スキップすることを学習している場合は、お勧めします。学習曲線は急ですが、バインドとコマンド、および WPF に関する重要で優れた機能についてすべて学習します。

于 2010-01-27T14:29:45.653 に答える
0

WPF でデータソースにバインドすると、「AllRoles」と呼ばれるウィンドウのデータ コンテキストのプロパティが検索されます。xaml でのデータ バインディングの詳細については、Model-View-ViewModel パターンを確認してください。 http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

于 2010-01-27T14:31:23.140 に答える