在绑定情况下,ItemsSource与DataContext的区别

15

我的主要问题是关于在一个场景中有多个控件源(例如数据网格中的组合框)或同时具有数据上下文和项源时,如何确定绑定使用哪个源?(是否有任何语法可以澄清这一点)

假设一个数据网格具有itemssource="球员列表"和datacontext="经理",并且其中有一个组合框作为某一列。我们还假设每个球员都有一个Inventory属性,它是一个集合类型。

然后在datagird.columns中:

  1. 每个列的当前绑定源是球员(这是我目前的理解)。我们只能绑定到球员的属性而不是"datacontext"经理的属性。没有办法绑定到“Manager”的属性。我理解的对吗?
  2. 然而,如果我们移动到组合框列,则假设让组合框的itemssource ='player's inventory',那么comboboxItem的当前源将是库存中的每个项目。如果使用绑定,它只能绑定到这些项目的属性。然而,有时我会看到代码,我们也可以绑定到组合框的属性内部的球员属性,特别是SelectedValue和SelectedItem。我有点困惑,请你帮我解答一下?

谢谢

2个回答

15

关键控件是一个ItemsControlComboBox继承自ItemsControlDataGrid的行为非常相似)。

ItemsControl具有类型为IEnumerableItemsSource属性。它还具有ItemTemplate属性。它将ItemsSource中的每个项目创建一个ItemTemplate的副本ItemTemplateDataContext将是ItemsSource中的每个项目。

在您的ComboBox的情况下,DataGrid列的DataContext将是您的Player对象。如果您将ComboBoxItemSource绑定到Player的库存,则将获取ComboBox列表中的每个项目。
需要注意的是ComboBox本身的DataContext未更改。它仍然是Player对象。如果您为ComboBox指定了ItemTemplate,那么将ItemTemplateDataContext设为Player库存中的项目。


1
对于 SelectedValue 和 SelectedItem,如果我们有绑定,则它将绑定到组合框数据上下文的属性(而不是组合框项源中每个项目的属性)。因此,现在是 Player 的属性,它是组合框的数据上下文。对于 SelectedValuePath 和 DisplayMemberPath:我们不使用标记语法来为它们分配值,因此它基本上不是绑定。这就是为什么我们仍然可以为其项源中的项目的属性名称分配名称(而不是数据上下文的属性)。我是正确的吗? - Tai

10

这真的很简单。

DataContext指的是项目的相同属性。它不会被扩展,也不是动态的。DataContext适用于当前位于父级内部的子级属性。

但是ItemsSource是动态的。它会随着源的扩展而扩展。这是一个很好的例子。

这是一个示例XAML。

 <UserControl x:Class="SilverlightApplication"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.Resources>           
        <DataTemplate x:Key="template2">
            <StackPanel Orientation="Horizontal">
                <Image x:Name="img1" Source="{Binding Image}"></Image>
                <TextBlock x:Name="data2" Text="{Binding Data}"></TextBlock>
            </StackPanel>
        </DataTemplate>
    </Grid.Resources>
    <StackPanel>
        <StackPanel x:Name="DataContextStack" Orientation="Vertical">
            <TextBlock x:Name="data1" Text="{Binding Text1}"></TextBlock>
            <TextBlock x:Name="data2" Text="{Binding Text2}"></TextBlock>
        </StackPanel>
        <ListBox x:Name="lst2" ItemTemplate="{StaticResource template2}"></ListBox>
    </StackPanel>
</Grid>

这是后台的代码。
 namespace SilverlightApplication
 {
  public partial class MainPage : UserControl
 {
    public MainPage()
    {
        InitializeComponent();
        loadLists();
    }

    private void loadLists()
    {
        ObservableCollection<Temp2> tColl = new ObservableCollection<Temp2>();            

        Temp1 t1 = new Temp1();
        t1.Text1 = "DataContext1";
        t1.Text2 = "DataContext2";            

        tColl.Add(new Temp2() { Image = "", Data = "Item1" });
        tColl.Add(new Temp2() { Image = "", Data = "Item2" });


        DataContextStack.DataContext = t1;
        lst2.ItemsSource = tColl;            
    }
}

public class Temp1
{
    public string Text1 { get; set; }
    public string Text2 { get; set; }
    


}

public class Temp2
{
    public string Image { get; set; }
    public string Data { get; set; }
}
}

如你所见,DataContext适用于存在于StackPanel中并引用一个名为Text的单一属性的TextBlock。
而ItemsSource则是指Image的源和TextBlock的Text属性,列表中的项可以随着ObservableCollection的扩展而增加。
或者更简单地说给你听。
DataContext - 值是根据设计设置的。 ItemsSource - 值是根据逻辑设置的。
希望这能帮到你。
如果这回答了你的问题,请将其标记为答案。

嗨Aswin,谢谢你的帮助。我理解你的例子,但我想问的是在同一控件中同时具有itemssource和datacontext的情况(即datagrid中包含combobox列的情况)。我认为Stephan的答案解决了我的大部分困惑。您的回答也很有帮助。谢谢 - Tai
1
这是同样的事情。如果您有一个带有2个文本块的列表框,就像我在示例中所说的那样。您可以使用DataContext来绑定数据。如果它具有不同的控件作为其子项,则使用ItemsSource将是最佳选项。两者都是在不同场景中使用的数据绑定现象。 - Aswin Ramakrishnan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接