CompositeCollection的源代码:为什么我不能绑定另一个控件的数据上下文但必须使用CollectionViewSource?

Em1*_*Em1 5 data-binding wpf compositecollection collectionviewsource

我最近提出的另一个问题中,我被告知使用a CompositeCollection来访问各种来源ListBox.

该示例使用a XmlDataProvider来提供一些虚拟数据.但是,我有一个包含数据的视图模型.

我花了一些时间来绑定ListBox视图模型的数据.最终我明白了,但现在我想明白为什么我以前的方法不起作用.

成功的关键是CollectionViewSource.我最初的尝试是:

<CollectionContainer Collection="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Movies}"/>
<CollectionContainer Collection="{Binding ElementName=Window, Path=DataContext.Movies}"/>
Run Code Online (Sandbox Code Playgroud)

我的想法是找到具有相应DataContext的Window,并绑定数据.你可以通过FindAncestor或通过ElementName,所以我尝试了两个.这对我来说似乎很合乎逻辑,但显然我错了.我运行应用程序时没有看到任何内容.
我还尝试绑定另一个具有数据上下文的控件; 例如StackPanel.

那么,为什么我不用1FindAncestorElementName1获取数据,但必须CollectionViewSource明确提供?


这是正在运行的代码.

<StackPanel DockPanel.Dock="Top">
    <ListBox ItemTemplateSelector="{StaticResource CustomDataTemplateSelector}">
        <ListBox.Resources>
            <CollectionViewSource x:Key="ViewSource" Source="{Binding Movies}"/>
        </ListBox.Resources>
        <ListBox.ItemsSource>
            <CompositeCollection>
                <CollectionContainer Collection="{Binding Source={StaticResource ViewSource}}"/>
                <CollectionContainer Collection="{Binding Source={StaticResource MyButtonsData}}"/>
            </CompositeCollection>
        </ListBox.ItemsSource>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True"
                   Width="{Binding (FrameworkElement.ActualWidth),
                               RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

1不,我没有忘记给窗户命名,也没有打字错误.

Em1*_*Em1 6

在microsoft.com上发现了一个讨论该问题的帖子.
似乎这个'bug'已知多年,但从未被修复过.

CollectionViewSource也在那里使用我正在使用的解决方法.

此外,你确实不能使用ElementName.我不知道是什么原因,但解决办法ElementName是使用x:Reference在其他问题的线程建议.

<CollectionContainer Collection="{Binding Source={x:Reference dummy}, Path=DataContext.Movies}"/>
Run Code Online (Sandbox Code Playgroud)

有趣的是,XAML编译器object reference not set to an instance of an object在编辑时会显示错误.
如果您没有使用祖先类型,则可以编译并运行,因为由于循环依赖性,您将获得XmlParseException.

要避免循环依赖性错误,可以将CompositeCollection放在资源中并通过StaticResource链接到那里.然后你也可以使用祖先类型.

<ListBox.Resources>
    <CompositeCollection x:Key="CompositeCollection">
        <CollectionContainer Collection="{Binding Source={x:Reference stackPanel}, Path=DataContext.Movies}"/>
    </CompositeCollection>
</ListBox.Resources>
<ListBox.ItemsSource>
    <CompositeCollection>
        <CollectionContainer Collection="{Binding Source={StaticResource CompositeCollection}}"/>
    </CompositeCollection>
</ListBox.ItemsSource>
Run Code Online (Sandbox Code Playgroud)