7

Я немного смущен тем, как привязка данных работает при использовании этих типов.CompositeCollection/CollectionViewSource confusion

Я читал, что вы не можете сделать следующее

public partial class Window1 : Window 
    { 
     public ObservableCollection<string> Items { get; private set; } 

     public Window1() 
     { 
      Items = new ObservableCollection<string>() { "A", "B", "C" }; 
      DataContext = this; 
      InitializeComponent(); 
     } 
    } 

<Window x:Class="WpfApplication25.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <ComboBox> 
     <ComboBox.ItemsSource> 
      <CompositeCollection> 
       <CollectionContainer Collection="{Binding Items}"/> 
      </CompositeCollection> 
     </ComboBox.ItemsSource> 
    </ComboBox> 
</Window> 

потому что CompositeCollection не имеет ни малейшего представления о DataContext и так ничего внутри него с помощью привязки должен установить свойство Source. Такие, как:

<Window x:Class="WpfApplication25.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <Window.Resources> 
     <CollectionViewSource x:Key="list" Source="{Binding Items}"/> 
    </Window.Resources> 

    <ComboBox Name="k"> 
     <ComboBox.ItemsSource> 
      <CompositeCollection> 
       <CollectionContainer Collection="{Binding Source={StaticResource list}}"/> 
      </CompositeCollection> 
     </ComboBox.ItemsSource> 
    </ComboBox> 
</Window> 

Но как это работает? он устанавливает источник что-то, но что-то, в этом случае CollectionViewSource использует datacontext (поскольку он явно не устанавливает источник).

Итак, поскольку в ресурсах Window объявлен «список», означает ли это, что он получает Windows DataContext? В таком случае, почему не работает следующее?

<Window x:Class="WpfApplication25.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <Window.Resources> 
     <Button x:Key="menu" Content="{Binding Items.Count}"/> 
    </Window.Resources> 

    <ComboBox Name="k"> 
     <ComboBox.ItemsSource> 
      <CompositeCollection> 
       <ContentPresenter Content="{Binding Source={StaticResource menu}}"/> 
      </CompositeCollection> 
     </ComboBox.ItemsSource> 
    </ComboBox> 
</Window> 

ответ

4

ты прав CompositeCollection не имеет никакого понятия datacontext поэтому не может унаследовать его от своего родителя.

из MSDN:
CompositeCollection can contain items such as strings, objects, XML nodes, elements, as well as other collections. An ItemsControl uses the data in the CompositeCollection to generate its content according to its ItemTemplate. For more information about using ItemsControl objects to bind to collections, see the Binding to Collections section of the Data Binding Overview.

на ваш вопрос
But how is that working? it sets the source to something, but that something, in this case a CollectionViewSource uses a DataContext (as its not explicitly setting a source).

Я думаю, вы думаете над его, Collection DependecyProperty может связываться с любым IEnumerable типа, так что не имеет значения, как коллекция была созданный до тех пор, пока он создан и реализует IEnumerable.
в вашем случае CVS наследует DataContext из окна, а затем привязывается к Items.

относительно вашего второго примера это не работает, потому что ContentPesenter нуждается в dataContext для работы, так как он мог наследовать его, механизм привязки просто установил себя как dataContext, даже если вы попытались связать контент Source с кнопкой, вы забыли для установки пути, я думаю, именно поэтому он проигнорировался. все, что вам нужно сделать, чтобы заставить его работать, это просто так:

<ContentPresenter Content="{Binding Source={StaticResource menu}, Path=Content}"/ 
+1

Почему это не получается? повысьте это! – Tuco