I'm trying to makeaA grouped listbox. Firstly I did a ItemTemplate. Now I'm trying to group the data but I don't have any idea how to use that ItemTemplate. Could anybody help me a little?
My current listbox xaml
<ListBox x:Name="kontakty" ItemsSource="{Binding kontakt}">
<ListBox.GroupStyle>
<GroupStyle HeaderStringFormat="Group">
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<StackPanel>
<TextBlock Text="{Binding Path=Name}" Foreground="Red"/>
<ComboBox ItemsSource="{Binding Path=Items}" DisplayMemberPath="Name"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
//...............//
</ListBox.ItemTemplate>
</ListBox>
Solution is adding ItemControl with this ItemTemplate to GroupStyle.
Related
I am using DataGrig Grouping for my data. In my group header I am using checkboxes for ColumnCheckBox cell check, for that I have to have rows data for each group.
XAML:
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount, StringFormat=({0})}"/>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter/>
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
CS:
Instances = new ListCollectionView(types);
Instances.GroupDescriptions.Add(new PropertyGroupDescription("View"));
Instances.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
Instances.GroupDescriptions.Add(new PropertyGroupDescription("Family"));
So an idea is to bind header checkboxes with array of Id for each row and on header check, change binded CheckColumn values. But for that i need to collect all group rows. Is it possible to implement?
So I've got: https://i.ibb.co/7g9GpqL/p1.png
And I need : https://i.ibb.co/WW7S4cn/p2.png
I have a datagrid with 3 level grouping. Grouping is done in code behind using the CollectionView and PropertyGroupDescription.
Every row of record will have a DataTemplateColumn (CheckBox). I included a checkbox infront of each header so that I can check all the child data.
Unfortunately I have tried few methods but i cant check all the child checkboxes.
xaml codes
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander x:Name="MyExpander" IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<CheckBox Click="checkBoxHeader_Click"/>
<TextBlock x:Name="MyExpanderHeader" Text="{Binding Name}" FontWeight="Bold" VerticalAlignment="Bottom">
</TextBlock>
</StackPanel>
</Expander.Header>
<ItemsPresenter Margin="20,0,0,0"/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
cs code
CollectionView collectionView = (CollectionView)CollectionViewSource.GetDefaultView(m_stationInfoList);
PropertyGroupDescription groupDescription1 = new PropertyGroupDescription("Property1");
PropertyGroupDescription groupDescription2 = new PropertyGroupDescription("Property2");
PropertyGroupDescription groupDescription3 = new PropertyGroupDescription("Property3");
collectionView.GroupDescriptions.Clear();
collectionView.GroupDescriptions.Add(groupDescription1);
collectionView.GroupDescriptions.Add(groupDescription2);
collectionView.GroupDescriptions.Add(groupDescription3);
In my WPF app I have a ListView of documents with grouping of sections:
myitems.Add(new Data("document_1", "section_1"));
myitems.Add(new Data("document_1", "section_2"));
myitems.Add(new Data("document_2", "one_and_only_section"));
lv.ItemsSource = myitems;
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lv.ItemsSource);
view.GroupDescriptions.Clear();
view.GroupDescriptions.Add(new PropertyGroupDescription("document");
This results in something that roughly looks like
< document_1
section_1
section_2
< document_2
one_and_only_section
This is in theory fine, but it is very tedious to select the "one_and_only_section" item if everything is collapsed, because it needs two clicks (first on "document_2", second on "one_and_only_section"). Ideally, the document_2 shouldn't be grouped in the same way as document_1:
< document_1
section_1
section_2
document_2
So if there is just one element to a group, it shouldn't have an expander and reveal that one element. If selected it should act as if "one_and_only_section" is selected.
Is this feasible with ListView?
I was able to produce the desired output with the following XAML code:
<ListView ItemsSource="{Binding Path=ItemsView}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<ControlTemplate.Resources>
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<TextBlock Text="{Binding Path=Section}" />
</DataTemplate>
</ControlTemplate.Resources>
<Expander Background="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}">
<Expander.Header>
<StackPanel Margin="0,8,0,0"
HorizontalAlignment="Stretch"
Orientation="Horizontal">
<TextBlock x:Name="Title"
VerticalAlignment="Center"
FontWeight="Bold">
<Run Text="{Binding Path=Name, Mode=OneWay}" />
<Run Text=" " />
<Run Text="{Binding Path=Items.Count, Mode=OneWay}" />
</TextBlock>
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Items.Count}" Value="1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<ControlTemplate.Resources>
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<TextBlock Text="{Binding Path=Document}" />
</DataTemplate>
</ControlTemplate.Resources>
<ItemsPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
You might want to add some extra attention to your expander style and the datatemplates, to make it look similar.
I have a WPF Prism project and it has a Region base on ItemControl:
<ItemsControl prism:RegionManager.RegionName="WorkspaceRegion" >
In this ItemControl i see some of my Views verticaly well but i want give a style to each Item of ItemControl (each View).
All of items (views) must have same style (for example: background
color, padding, margin, border and...)
I want something like this (for example):
I used a simple style and code like this:
<ItemsControl prism:RegionManager.RegionName="WorkspaceRegion" Background="#765e4d" Margin="10">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Red" Padding="10" BorderThickness="1" CornerRadius="5">
<ContentPresenter Content="{Binding}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Its Error:
A style intended for type 'ItemsControl' cannot be applied to type
'View1'
Also i tested this codes:
<ItemsControl prism:RegionManager.RegionName="WorkspaceRegion" Background="#765e4d" Margin="10">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid >
<TextBlock Text="Test"/>
<Border BorderBrush="Red" Padding="10" Margin="10" BorderThickness="1" CornerRadius="5">
<ContentPresenter Content="{Binding}"/>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
But the result is like when i write:
<ItemsControl prism:RegionManager.RegionName="WorkspaceRegion" >
Why? What is my mistake?
How can i do this?
Edit1:
I used <ItemsPresenter/> instead of <ContentPresenter Content="{Binding}"/>
Result: without any change
Edit2:
I write this style for ItemContainerStyle property of the ItemsControl and it works if i remove ControlTemplate part from it.
Now the question is which kind of Presenter or Xaml Tag i should use inside the following ControlTemplate to my Views (UserControls) be shown.
<Style TargetType="{x:Type UserControl}" x:Key="MyItemContainerStyle">
<Setter Property="Background" Value="Brown"/>
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="Template" >
<Setter.Value>
<ControlTemplate>
??????????????????????????
<!-- The following ContentPresenter not working and the Items dose not show -->
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Set the ContentTemplate property of the style, not Control.Template or Template
An ItemsControl gets rendered like this :
<ItemsControl>
<ItemsPanel>
<ContentPresenter>
<ItemTemplate>
</ContentPresenter>
<ContentPresenter>
<ItemTemplate>
</ContentPresenter>
<ContentPresenter>
<ItemTemplate>
</ContentPresenter>
</ItemsPanel>
</ItemsControl>
The ItemContainerStyle applies to the ContentPresenter object that wraps each item in this XAML tree, and I don't believe a ContentPresenter has either a Control.Template or a Template property.
When changing how a ContentPresenter is displayed you should overwrite the ContentTemplate property instead.
This works for me in my test application:
<ItemsControl Background="#FF85664F" prism:RegionManager.RegionName="WorkspaceRegion">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="DarkGray" Padding="10"
Margin="5, 5, 5, 0" BorderThickness="1"
CornerRadius="5" Background="#FFC3BF8F">
<ContentPresenter Content="{Binding}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<system:String>ItemsControl Item #1</system:String>
<system:String>ItemsControl Item #2</system:String>
<system:String>ItemsControl Item #3</system:String>
<system:String>ItemsControl Item #4</system:String>
<system:String>ItemsControl Item #5</system:String>
</ItemsControl>
I'm having a problem where when adding grouping to my datagrid; the event I have defined as "Checkbox.Checked" gets called when it shouldn't be.
When this line of code is not commented out "collection.GroupDescriptions.Add(new PropertyGroupDescription("_group"));" the bug occurs.
Upon starting my application with this line in, the first check of any checkbox works as it should, then on the second click, if I click literally anywhere on the datagrid, the checked event will be fired.
Do any of you have any idea?
Thanks.
I have events define on my DataGrid like this;
<DataGridCheckBoxColumn.CellStyle>
<Style>
<EventSetter Event="CheckBox.Checked" Handler="Method_checked"/>
<EventSetter Event="CheckBox.Unchecked" Handler="Method_Unchecked"/>
</Style>
</DataGridCheckBoxColumn.CellStyle>
I have since added grouping to my data using the following code in C#;
ListCollectionView collection = new ListCollectionView(listOfData);
collection.GroupDescriptions.Add(new PropertyGroupDescription("_group"));
dgData.ItemsSource = collection;
I have added groups to my datagrid adding the following code in xaml;
<DataGrid.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
You may noticed "GroupHeaderStyle" which is defined above;
<Window.Resources>
<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="exp" IsExpanded="True"
Background="White"
Foreground="Black">
<Expander.Header>
<TextBlock Text="{Binding Name}" />
</Expander.Header>
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>