CompositeCollection / CollectionViewSource混淆

时间:2013-05-22 22:56:15

标签: wpf datacontext collectionviewsource staticresource compositecollection

我对使用这些类型时数据绑定的工作方式感到有些困惑。

我读过你不能做以下的事情

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(因为它没有明确设置源)。

因为“list”是在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>

1 个答案:

答案 0 :(得分: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从Window继承DataContext,然后绑定到Items

关于你的第二个例子,它不起作用,因为ContentPesenter需要dataContext才能工作,因为它可以继承它,即使你试图将内容Source绑定到按钮,绑定机制也只是将自己设置为dataContext ,你忘了设置路径,我想这就是它被忽略的原因。 所有你需要做的就是设置它:

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