I want to realize a custom view just like ListView.
Now the problem is I want get a Tapped event from group header, maybe more.
It always creates GroupItem as group view, and can't be change.
I found what ListView do is create ListViewHeaderItem by the system and added to the visual tree when realizing the GroupStyle.HeaderTemplate.
My question is any way to do this?
cs:
public class CustomView : ItemsControl
xaml:
<CollectionViewSource x:Name="itemCVS" IsSourceGrouped="True"
Source="{x:Bind Groups}" ItemsPath="Items"/>
...
<CustomView ItemsSource="{x:Bind itemCVS.View}">
<CustomView.GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<CustomPanel/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</CustomView.GroupStyle>
</CustomView>
CustomView Visual Tree:
CustomView
Windows.UI.Xaml.Controls.Border
Windows.UI.Xaml.Controls.ScrollViewer
Windows.UI.Xaml.Controls.Border
Windows.UI.Xaml.Controls.Grid
Windows.UI.Xaml.Controls.ScrollContentPresenter
Windows.UI.Xaml.Controls.ItemsPresenter
Windows.UI.Xaml.Controls.ContentControl
CustomPanel
Windows.UI.Xaml.Controls.GroupItem
Windows.UI.Xaml.Controls.Grid
Windows.UI.Xaml.Controls.ContentControl
Windows.UI.Xaml.Controls.ContentPresenter
Windows.UI.Xaml.Controls.TextBlock
Windows.UI.Xaml.Controls.ItemsControl
Windows.UI.Xaml.Controls.ItemsPresenter
Windows.UI.Xaml.Controls.ContentControl
CustomPanel
Item 1
Item 2
ListView Visual Tree:
Windows.UI.Xaml.Controls.ListView
Windows.UI.Xaml.Controls.Border
Windows.UI.Xaml.Controls.ScrollViewer
Windows.UI.Xaml.Controls.Border
Windows.UI.Xaml.Controls.Grid
Windows.UI.Xaml.Controls.ScrollContentPresenter
Windows.UI.Xaml.Controls.ItemsPresenter
Windows.UI.Xaml.Controls.ContentControl
Windows.UI.Xaml.Controls.ItemsStackPanel
Windows.UI.Xaml.Controls.ListViewHeaderItem
Windows.UI.Xaml.Controls.ListViewHeaderItem
Windows.UI.Xaml.Controls.ListViewItem 1
Windows.UI.Xaml.Controls.ListViewItem 2
You code has generated the HeaderItem.
Because your CustomerView inherits from ItemsControl, the generated HeaderItem has no style.
So if you want to do this, please manually add to change the style like following.
<CustomerView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<ListViewHeaderItem>
<StackPanel>
<TextBlock Text="{Binding Key}"/>
</StackPanel>
</ListViewHeaderItem>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</CustomerView.GroupStyle>
Related
I have 3 List views. They are very similar. The only difference is that their ItemsSource binds to different variables. Is there a way to create a template list view with unknown ItemsSource, and I can pass a parameter to fill that ItemsSource?
My code is something like this:
<ListView Name="View1" ItemsSource={"Binding Student1"}>
<TextBlock Text={"Binding Name"}/>
</ListView>
<ListView Name="View2" ItemsSource={"Binding Student2"}>
<TextBlock Text={"Binding Name"}/>
</ListView>
<ListView Name="View3" ItemsSource={"Binding Student3"}>
<TextBlock Text={"Binding Name"}/>
</ListView>
Edit:
I might have expressed my question in a wrong way. I would like to have a separate user control view called "StudentView":
<ListView ItemsSource=Parameter1>
<TextBlock Text={"Binding Name"}/>
</ListView>
So that in my main window, I can do something like this:
<local:StudentView Parameter1={"Binding Student1"}/>
You are on the right track with thinking about templating
What you are looking for is something called a ControlTemplate.
Your ControlTemplate would then target the ListView control and use the key word TemplateBinding to pass through the ItemsSource binding from your ListView
You would look to add this as a window resource as shown below.
<Window.Resources>
<ControlTemplate x:Key="ListViewTemplate" TargetType="ListView">
<ListView ItemsSource="{TemplateBinding ItemsSource}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ControlTemplate>
</Window.Resources>
This would enable you to use this template on your ListView controls as shown below
<ListView Template="{StaticResource ListViewTemplate}" ItemsSource="{Binding PersonList}"/>
<ListView Template="{StaticResource ListViewTemplate}" ItemsSource="{Binding PersonList1}"/>
<ListView Template="{StaticResource ListViewTemplate}" ItemsSource="{Binding PersonList2}"/>
Hope this gives you what you were looking for
So, I have an ItemsControl with an ItemTemplate to visualize the items in it's ItemsSource.
This Template is a DataTemplate with some controls in it.
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock/>
<TextBlock/>
<!-- Content depending on item type -->
<ContentPresenter Content="{Binding}" ContentTemplateSelector="{StaticResource TemplateSelector}"/>
<TextBlock/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The items in the ItemsSource can be of different types. Most of the properties of the different types are the same but some properties are different. So I want to put the common content directly inside the DataTemplate but for the content that differs I want to have some kind of placeholder that displays only type-specific content.
So I tried a ContentPresenter with a ContentTemplateSelector. But this does not work. When I set the Content, the TemplateSelector is never called and the name of the underlying viewmodel is displayed. When I do not set the Content, the TemplateSelector is called, but the item in the SelectTemplate function is null.
I do not want to make the whole DataTemplate for each DataType because most of the content is the same and I would have much duplicate code.
You do not need a DataTemplateSelector.
Just set the DataType of different DataTemplates in the ItemsControl's Resources. The DataTemplates would automatically be selected according to the type of the item.
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:Item1}">
<TextBlock Text="{Binding Item1Property}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Item2}">
<TextBlock Text="{Binding Item2Property}"/>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock ... />
<ContentPresenter Content="{Binding}"/>
<TextBlock ... />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I'm using a Listbox to show multiple items.
The items are grouped. Now I want to edit the header style but the only thing happens is that the text isn't shown anymore.
Thats my xaml:
<ListBox x:Name="lbTreatments" HorizontalAlignment="Left" Height="473" Margin="10,37,0,0" VerticalAlignment="Top" Width="309" FontSize="13">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding subcategoryName}" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And thats my code to group the items:
ICollectionView view = CollectionViewSource.GetDefaultView(treatmentsCategory);
view.GroupDescriptions.Add(new PropertyGroupDescription("subcategoryName"));
view.SortDescriptions.Add(new SortDescription("subcategoryName", ListSortDirection.Ascending));
lbTreatments.ItemsSource = view;
The items are grouped but the header text is missing. If I delete the Groupstyle from xaml the text will be shown. Can anybode help me please?
MSDN says:
Each group is of type CollectionViewGroup.
The actual data type is CollectionViewGroup which doesn't have a subcategoryName property so the binding will fail. Instead you have to use the Name property, which will already be set to the value from subcategoryName.
As such, use this...
<TextBlock Text="{Binding Name}"/>
...in your header template to get the group name.
I'm totaly new to wpf. I try to create a nested datatemplate like this layout (datatemplate inside another datatemplate). I managed to create a datatemplate and to connect to "Object A" in an ObservableCollection, which worked really well. Now I need to have a nested ObservableCollection in each Object A to display Object B and Object C in columns. But I don't really know how to do that and can't find examples.
Maybe anyone could give me a hint?
Thanks and regards,
Marlene
Assuming you're using a ListView or ListBox to display a collection of Object A (lets call it ObjectACollection), and that Object A has properties named (in this example) ObjectBCollection and ObjectCCollection you could do something like this:
<UserControl xmlns:namespaceA="clr-namespace:MyProj.Models.ObjectANamespace"
xmlns:namespaceB="clr-namespace:MyProj.Models.ObjectBNamespace"
xmlns:namespaceC="clr-namespace:MyProj.Models.ObjectCNamespace" >
<ListBox ItemsSource="{Binding ObjectACollection}">
<ListBox.ItemTemplate>
<DataTemplate DataType="namespaceA:ObjectA">
<StackPanel Orientation="Horizontal">
<ListBox ItemsSource="{Binding ObjectBCollection}">
<ListBox.ItemTemplate>
<DataTemplate DataType="namespaceB:ObjectB">
<TextBlock Text="{Binding ObjectBProperty}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding ObjectCCollection}">
<ListBox.ItemTemplate>
<DataTemplate DataType="namespaceC:ObjectC">
<TextBlock Text="{Binding ObjectCProperty}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>
im working on a menu which can display items.
Therefor i have a UserControl 'MenuItem' which displays an entity of the type 'MenuItemEntity'.
Cause there are submenus which are displayed in a different way there is another UserControl 'MenuItemGroup' which are bound to an entity of type 'MenuItemGroupEntity' containing different MenuItemEntities.
Now i have the following Problem:
The 'menu' should be bound to an entity of the type 'MenuEntity'.
Inside this i want to have an ObservableCollection which contains MenuItemEntity's AND MenuItemGroupEntity which are displayed in an StackPanel using an ItemsControl.
But i dont know if there is any way to analyze the actual element in the bound collection to draw either an MenuItem or an MenuItemGroup. Something like a switch maybe?
Normaly i would bind the items of the ObservableCollection in the 'MenuEntity' like this:
<ItemsControl ItemsSource="{Binding MenuItemAndGroupCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- IS THERE ANY WAY TO SWITCH BASED ON THE CLASS TYPE? -->
<local:MenuItemGroup DataContext="{Binding}" />
<local:MenuItem DataContext="{Binding}" />
<!-- IS THERE ANY WAY TO SWITCH BASED ON THE CLASS TYPE? -->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I hope someone can help me out of this =(
Simply use "implicit" DataTemplates, like this:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:MyClass1}">
<local:MyUserControl1/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:MyClass2}">
<local:MyUserControl2/>
</DataTemplate>
<!-- and so on... -->
</Window.Resources>
<ItemsControl ItemsSource="{Binding MenuItemAndGroupCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- Do NOT specify an ItemTemplate here -->
</ItemsControl>
</Window>