对ListView和DataContext的一些困扰

Kai*_*Kai 2 c# data-binding wpf datacontext xaml

我编写了以下C#和XAML代码:

namespace ListViewExample1
{
public partial class MainWindow : Window
{
    public ObservableCollection<MyColleague> myCollegues = new ObservableCollection<MyColleague>();

    public MainWindow()
    {
        myCollegues.Add(new MyColleague() { Name = "Tim", Surname = "Meier" });
        myCollegues.Add(new MyColleague() { Name = "Martin", Surname = "Hansen" });
        myCollegues.Add(new MyColleague() { Name = "Oliver", Surname = "Drumm" });


        InitializeComponent();
    }

    public ObservableCollection<MyColleague> MyColleagues 
    {
        get { return this.myCollegues; }
    }
}

public class MyColleague
{
    public String Name { get; set; }

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

XAML代码:

<Grid>
    <ListView ItemsSource="{Binding}" DataContext="{Binding RelativeSource={RelativeSource ListViewExample1:MainWindow}, Path=myCollegues}">
        <ListView.View >
            <GridView >
                <GridViewColumn Header="Name" Width="150" DisplayMemberBinding="{Binding Name}"/>
                <GridViewColumn Header="Surname" Width="150" DisplayMemberBinding="{Binding Surname}"/>
            </GridView>
        </ListView.View>
    </ListView> 
</Grid>
Run Code Online (Sandbox Code Playgroud)

现在,我需要设置数据上下文,但是此时我有些烦恼。哪种DataContext语法正确?

Rob*_*ney 5

有多种设置方法DataContext; 没有人天生就是对的。

值得注意的是,DataContext如果您只需要绑定一个属性(ItemsSource在本例中为),则根本没有理由设置项目控件。设置DataContext简化了绑定多个属性,因为所有绑定都使用相同的上下文。

如果您想在没有任何代码隐藏的情况下进行数据绑定(如您在评论中所述),那么您选择的示例不是很好,因为您是在代码隐藏中创建对象。尝试使用无参数构造函数创建一个类,例如:

public class MyColleagueCollection : ObservableCollection<MyColleague>
{
   public MyColleagueCollection()
   {
       Add(new MyColleague() { Name = "Tim", Surname = "Meier" });
       Add(new MyColleague() { Name = "Martin", Surname = "Hansen" });
       Add(new MyColleague() { Name = "Oliver", Surname = "Drumm" });
   }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以执行以下操作:

<ListView>
   <ListView.ItemsSource>
      <local:MyColleagueCollection/>
   </ListView.ItemsSource>
   ...
</ListView>
Run Code Online (Sandbox Code Playgroud)

或者,您可以设置DataContext,然后将设置ItemsSource"{Binding}"。或在资源字典中创建对象,然后使用绑定StaticResource

您还可以将集合创建为类的属性(而不是字段,因为x0r正确指出),Window然后执行以下操作:

<Window DataContext="{Binding RelativeSource={RelativeSource Self}}"...
Run Code Online (Sandbox Code Playgroud)

现在,Window它本身就是数据上下文对象,允许窗口中的任何元素直接绑定到其属性,而无需使用RelativeSource

或者(我们还差得远),您可以给窗口命名,然后按名称绑定到该窗口:

<ListView ItemsSource=`{Binding ElementName=MyWindow, Path=MyCollection}"...
Run Code Online (Sandbox Code Playgroud)

我们什至不去使用ObjectDataProvider

大多数人最终要做的事情-这与您将要找到的“正确”答案非常接近-为主窗口创建一个视图模型类,在窗口的构造函数中实例化它,并将该窗口设置DataContext为该对象。从那时起,主窗口显示的任何视图都将绑定到该视图模型的属性。请参阅Josh Smith的有关Model / View / ViewModel模式的文章,以获得一个非常好的示例。

绑定和数据上下文具有多种用途。当然,这也意味着您可能会出错。它与领土。但是,一旦了解了它们,就很少遇到真正的问题。