5

我最近提出的另一个问题中,有人告诉我使用 aCompositeCollection来访问 a 的各种来源ListBox

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

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

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

<CollectionContainer Collection="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Movies}"/>
<CollectionContainer Collection="{Binding ElementName=Window, Path=DataContext.Movies}"/>

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

那么,为什么我不使用FindAncestorand ElementName1获取数据,而必须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>

1不,我没有忘记给窗口命名,也没有错字。

4

1 回答 1

6

在 microsoft.com 上找到了一个讨论该问题的线程。
似乎这个“错误”已为人所知多年,但从未得到修复。

CollectionViewSource那里也建议了我正在使用 ( ) 的解决方法。

此外,您确实不能使用ElementName. 我不知道是什么原因,但解决方法ElementName是按照另一个问题的线程中的建议x:Reference使用。

<CollectionContainer Collection="{Binding Source={x:Reference dummy}, Path=DataContext.Movies}"/>

有趣的是,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>
于 2014-08-21T20:32:37.570 回答