Почему DataContext и ItemsSource не являются избыточными?
В WPF Databinding я понимаю, что у вас есть DataContext
, который сообщает элементу, какие данные он будет связывать, и ItemsSource
, который "выполняет привязку".
Но, например, в этом простом примере не кажется, что ItemsSource
делает что-нибудь полезное, так как что еще вы хотите, чтобы элемент выполнял с DataContext
, кроме привязки к нему?
<ListBox DataContext="{StaticResource customers}"
ItemsSource="{Binding}">
И в более сложных примерах ItemsSource
у вас есть Path и Source, которые, кажется, вторгаются на территорию DataContext
.
ItemsSource="{Binding Path=TheImages, Source={StaticResource ImageFactoryDS}}"
Каков наилучший способ понять эти два понятия, чтобы знать, когда и как применять каждый из них в различных сценариях кодирования?
Ответы
Ответ 1
DataContext
- это просто удобный способ выбрать контекст для привязок для случаев, когда явный источник не указан. Он унаследован, что позволяет сделать это:
<StackPanel DataContext="{StaticResource Data}">
<ListBox ItemsSource="{Binding Customers}"/>
<ListBox ItemsSource="{Binding Orders}"/>
</StackPanel>
Здесь Customers
и Orders
- это коллекции на ресурсе, называемом "Данные". В вашем случае вы могли бы просто сделать это:
<ListBox ItemsSource="{Binding Source={StaticResource customers}}"/>
поскольку никакому другому элементу управления не нужен контекст.
Ответ 2
Свойство ItemsSource будет привязано непосредственно к объекту коллекции. ИЛИ свойство коллекции объекта привязки свойства DataContext.
Exp:
Class Root
{
public string Name;
public List<ChildRoot> childRoots = new List<ChildRoot>();
}
Class ChildRoot
{
public string childName;
}
Существует два способа привязки элемента управления ListBox:
1) Связывание с DataContext:
Root r = new Root()
r.Name = "ROOT1";
ChildRoot c1 = new ChildRoot()
c1.childName = "Child1";
r.childRoots.Add(c1);
c1 = new ChildRoot()
c1.childName = "Child2";
r.childRoots.Add(c1);
c1 = new ChildRoot()
c1.childName = "Child3";
r.childRoots.Add(c1);
treeView.DataContext = r;
<TreeViewItem ItemsSource="{Binding Path=childRoots}" Header="{Binding Path=Name}">
<HierarchicalDataTemplate DataType="{x:Type local:Root}" ItemsSource="{Binding Path=childRoots}">
2) Связывание с ItemSource:
Свойство ItemsSource принимает коллекцию всегда.
здесь мы должны привязать коллекцию Root
List<Root> lstRoots = new List<Root>();
lstRoots.Add(r);
<HierarchicalDataTemplate DataType="{x:Type local:Root}" ItemsSource="{Binding Path=childRoots}">
В первом примере у нас есть привязка DataContext, у которой есть объект внутри этого объекта, который мы имеем в коллекции, который мы привязали к свойству ItemSource, где во втором примере мы напрямую связываем свойство ItemSource с объектом коллекции.