WPF ListBox具有多个不同类型的源

时间:2014-08-20 19:48:45

标签: wpf listbox itemssource multibinding

我实际上是为完全不同的东西设置了一个示例应用程序,但后来我尝试了这个:

我有一个Movies的集合。我将有一个显示所有电影的列表框。但是,列表框将它们作为按钮提供,以便您可以单击按钮并播放电影。

代码是:

<StackPanel DockPanel.Dock="Top">
    <ListBox ItemsSource="{Binding Movies}" SelectedItem="{Binding Path=SelectedMovie}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True"
                           Width="{Binding (FrameworkElement.ActualWidth),
                                   RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding Title}"
                        Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
                                  Path=DataContext.PlayMovieCommand}"
                        CommandParameter="{Binding Id}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

然后我想在最后添加一个Button,文本为“Add”,当我点击该按钮时,我可以添加一个新电影。

我找不到提供此解决方案的解决方案。在互联网上搜索时,我发现HierarchicalDataTemplateCompositeCollection;一开始看起来很有希望,但我没有按照我的意愿让它工作。我也在考虑MultiBinding,但我似乎又失败了。

所以,我想我的问题是:
如何在我的电影集中添加一个“添加”按钮?

或更通用: 如何将多个不同类型的数据源/集合添加到列表框中?

2 个答案:

答案 0 :(得分:1)

您可以创建对象列表,添加电影,然后添加其他类型,例如&#34; string&#34;宾语。然后,您需要创建从DataTemplateSelector派生的类,该类遍历List并确定元素是否为Movie对象。如果是,则返回正确的DataTemplate,否则返回DataTemplate for button。

class DTS : DataTemplateSelector
{
    public DataTemplate MovieTemplate { get; set; }
    public DataTemplate ButtonTemplate { get; set; }

    public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
    {
        return item is Movie ? MovieTemplate : ButtonTemplate;
    }
}

然后在XAML中你做

 <local:DTS x:Key="DTS" ButtonTemplate="{StaticResource ButtonTemplate}" MovieTemplate="{StaticResource MovieTemplate}"/>

请记住,在应用ButtonTemplate和MovieTemplate之前必须先创建它,因为StaticResource需要这个。 MovieTemplate与您已有的模板相同,仅在您的Button的字符串情况下提供模板。 最后,您将ItemTemplateSelector设置如下

   <ListBox ItemsSource="{Binding lista}" ItemTemplateSelector="{StaticResource DTS}"/>

结果你应该被显示出来 enter image description here

答案 1 :(得分:1)

使用CompositeCollectionDataTemplate作为类型。

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Page.Resources>
    <XmlDataProvider x:Key="MoviesData" XPath="Movies/Movie">
      <x:XData>
      <Movies xmlns="">
        <Movie Title="The Shawshank Redemption" />
        <Movie Title="The Godfather" />
        <Movie Title="The Dark Knight" />
      </Movies>
      </x:XData>
    </XmlDataProvider>
    <XmlDataProvider x:Key="MyButtonsData" XPath="MyButtons/MyButton">
      <x:XData>
      <MyButtons xmlns="">
        <MyButton Title="Add Movie" />
      </MyButtons>
      </x:XData>
    </XmlDataProvider>
    <DataTemplate DataType="Movie">
      <Button Content="{Binding XPath=@Title}"
              Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
                        Path=DataContext.PlayMovieCommand}"
              CommandParameter="{Binding Id}" />
  </DataTemplate>
    <DataTemplate DataType="MyButton">
      <Button Content="{Binding XPath=@Title}"
              Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
                        Path=DataContext.AddMovieCommand}" />
  </DataTemplate>  

  </Page.Resources>
    <ListBox>
      <ListBox.ItemsSource>
        <CompositeCollection>
        <CollectionContainer Collection="{Binding Source={StaticResource MoviesData}}"/>
        <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>
</Page>

以下是Kaxaml

中的结果

enter image description here