具有多个不同类型源的WPF列表框
我实际上是为完全不同的东西设置了一个示例应用程序,但后来我尝试了以下方法: 我有一套具有多个不同类型源的WPF列表框,wpf,listbox,itemssource,multibinding,Wpf,Listbox,Itemssource,Multibinding,我实际上是为完全不同的东西设置了一个示例应用程序,但后来我尝试了以下方法: 我有一套电影。我会有一个显示所有电影的列表框。但是,列表框将它们作为按钮提供,以便您可以单击按钮并播放电影 代码是: <StackPanel DockPanel.Dock="Top"> <ListBox ItemsSource="{Binding Movies}" SelectedItem="{Binding Path=SelectedMovie}"> <ListBo
电影
。我会有一个显示所有电影的列表框。但是,列表框将它们作为按钮提供,以便您可以单击按钮并播放电影
代码是:
<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>
然后我想在结尾添加一个按钮,文本为“Add”,当我点击该按钮时,我可以添加一部新电影
我没有找到一个解决方案来提供这一点。在搜索互联网时,我发现了层次数据模板
和复合收集
;起初,这两个项目看起来都很有希望,但我没能让它按我所希望的那样发挥作用。我也在考虑多重绑定,但我似乎又失败了
所以,我想我的问题是:如何将单个添加按钮添加到我的电影收藏中 或更通用:
如何将不同类型的数据源/集合添加到列表框中?您可以创建对象列表,添加电影,然后添加另一种类型,例如“字符串”对象。然后,您需要创建从DataTemplateSelector派生的类,该类贯穿整个列表并确定元素是否为Movie对象。如果是,则返回正确的DataTemplate,否则返回按钮的DataTemplate
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是与您已有的模板相同的模板,仅在按钮为字符串的情况下提供模板。
最后,您设置了ItemTemplateSelector,如下所示
<ListBox ItemsSource="{Binding lista}" ItemTemplateSelector="{StaticResource DTS}"/>
因此,你应该被展示出来
对类型使用
CompositeCollection
和DataTemplate
<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
我花了一些时间将列表与视图模型绑定,因为FindAncestor和ElementName都没有给我列表。但是,当我将CollectionViewSource添加到我的资源中并绑定到该源时,我就得到了我的电影列表。尽管如此,我还是必须实现另一个解决方案中建议的DataTemplateSelector我接受这个答案,因为它为我提供了如何向列表中添加多个源的基本概念。您不需要实现DataTemplateSelector。您需要研究
DataTemplate类的DataType
属性。好吧,在窗口中声明两个DataTemplate具有DataType属性。资源(或ListBox.Resources)是不够的。我没有看到电影的标题(我的意思是我看到了默认的模板,这在这里并不令人满意)。当我将DataTemplate放入List.ItemTemplate时,我只能使用其中一个,但至少我可以看电影。使用DataTemplateSelector解决了这个问题。上面的示例说明了另一个问题。您的回答对它的运行非常有帮助。然而,我不喜欢绑定对象类型的属性,它代表所有可能的数据(我想这就是你说的,对吧?)。我选择了另一个答案中提供的CompositeCollection解决方案,并将其与DataTemplateSelector相结合+1无论如何