WPF ListBox with multiple sources of different types

I actually created an example application for something completely different, but then I tried to do this:

I have a collection of Movies . I will have a list box in which all the films will be shown. However, the list box provides them in the form of buttons so that you can click on the button and play the movie.

The code:

 <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> 

Then I thought about adding one button to the end, with the text "Add", and when I click on this button, I can add a new movie.

I did not find a solution for this. When searching the Internet, I found HierarchicalDataTemplate and CompositeCollection ; both at first looked promising, but I was not able to get it to work as I want. I also thought about MultiBinding , but again I seem to fail.

So, I think my question is:
How to add one added button to my movie collection?

Or more general: How can I add several sources / collections of data of different types to the list?

0
source share
2 answers

Use the CompositeCollection and DataTemplate types for types.

 <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> 

Here is the result in Kaxaml

enter image description here

+1
source

You can create a list of objects, add movies, and then add another type, for example, "string". Then you need to create a class derived from a DataTemplateSelector that goes through the entire list and determines whether the item is a Movie object. If so, it returns the correct DataTemplate, otherwise it returns the DataTemplate for the 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; } } 

then in xaml you do

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

Keep in mind that ButtonTemplate and MovieTemplate must be created before using them, as StaticResource requires this. MovieTemplate is the same template that you already have, just specify a template in case of a string for your button. At the end you set ItemTemplateSelector as follows

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

As a result, you should be displayed enter image description here

+1
source

Source: https://habr.com/ru/post/1200876/


All Articles