I'm trying to group my ObservableCollection using CollectionViewSource, it seems to work for items but it's not showing the bind property value for GroupBox.
Here is what I'm trying:
I've List<Object> containing properties Description, Season. I want to group by Season. Here is my xml:
<mah:MetroWindow x:Class="eCatalog_Launcher.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:eCatalog_Launcher"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
mc:Ignorable="d"
Title="eCatalog Launcher"
WindowState="Maximized"
Loaded="MetroWindow_Loaded"
Closing="MetroWindow_Closing">
<Window.Resources>
<CollectionViewSource x:Key="catalogsBySeasons"
Source="{Binding Path=Catalogs, Mode=TwoWay}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Season" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Source={StaticResource catalogsBySeasons}}">
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<GroupBox Header="{Binding Season}">
<ItemsPresenter />
</GroupBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ItemsControl.GroupStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<mah:Tile Title="{Binding Description}"
Tag="{Binding}"
Style="{StaticResource SmallTileStyle}"
Click="Tile_Click">
<iconPacks:PackIconMaterial Width="32"
Height="32"
Margin="0, -30, 0, 0"
Kind="{Binding Kind}">
</iconPacks:PackIconMaterial>
</mah:Tile>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
It's showing the Season value as GroupBox Heading.
Is there anything wrong?
You should bind to the Name property of the group:
<ControlTemplate TargetType="{x:Type GroupItem}">
<GroupBox Header="{Binding Name}">
<ItemsPresenter />
</GroupBox>
</ControlTemplate>
This should display the actual value of the Season property that you group by.
Related
I'm trying to group a listbox. And all I can get to show up is the header.
I've got a list list of 'Online Users' , which look like this.
public class OnlineUser{
public string Branch {get;set;}
public string FirstName{get;set;}
public string LastName{get;set;}
}
Then i populate the list with some users, and put that list into a ICollectionView 'FilterableOnlineUsers'
FilterableOnlineUsers = CollectionViewSource.GetDefaultView(OnlineUsers);
FilterableOnlineUsers.GroupDescriptions.Add(new PropertyGroupDescription("Branch"));
FilterableOnlineUsers.SortDescriptions.Add(new SortDescription("Branch", ListSortDirection.Descending));
And in my Xaml:
<ListBox SelectedItem="{Binding DataContext.SelectedUser" ItemsSource="{Binding DataContext.FilterableOnlineUsers" >
<ListBox.GroupStyle>
<GroupStyle />
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="FirstName"></Binding>
<Binding Path="LastName"></Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
All I can get to show up in the Listbox is the branch name. I can't get first name or lastname to show up underneath the group Descriptions..
Thanks.
You should define a CollectionViewSource in XAML resource Like Below and make the ItemsSource set to the CollectionViewSource,
<CollectionViewSource x:Key="ListBoxItems" Source="{Binding Path=ListOfOnlineUser}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Branch" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
In List Box
<ListBox ItemsSource="{Binding Source={StaticResource ListBoxItems}}"/>
Detail
Below is the ListBox show grouped branch and each branch is inside an expander which you can collapse and expand each groups.
<ListBox
Margin="0,0,5,0"
ItemsSource="{Binding Source={StaticResource ListBoxItems}}"
SelectedIndex="-1"
SelectedItem="{Binding SelectedBranch}">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander
Padding="0"
BorderThickness="0"
Header="{Binding Name}"
IsExpanded="True">
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0">
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text="{Binding LastName}" />
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
In my WPF Application i'm having datagrid in this datagrid i want to grouping up data from database based on column name called "City" ,i'm not using mvvm architecture and list method,I'm Using ICollectionView and passed datatable object as a parameter,This is my c# code
ICollectionView cv = CollectionViewSource.GetDefaultView(dt);
cv.GroupDescriptions.Add(newPropertyGroupDescription("City"));
Hotels.ItemsSource = cv;
And This is my XAML Code:
<Window.Resources>
<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<StackPanel>
<TextBlock Text="{Binding City}" Name="grouping" Foreground="Black"></TextBlock>
<ItemsPresenter/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<DataGrid Background="Azure" ItemsSource="{Binding Hotels}" CanUserAddRows="False" Name="Hotels" Style="{StaticResource AzureDataGrid}" Margin="0,173,0,0">
<DataGrid.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource ResourceKey=GroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</DataGrid.GroupStyle>
</DataGrid>
It does not display text in textblock i'm binding Textblock with column name but it does't works...Please help me
If you don't use viewmodel for each item, but DataTable's row object, WPF can't recognize the name "City". You need to use group's name which is held by CollectionViewGroupInternal.Name property of object representing a group item. In this particular scenario it's the name of the city. Just bind Name to your TextBlock.
You can achieve your goal in less lines of code using group's HeaderTemplate. Default ItemPresenter will be visible below the Header.
<!-- resources -->
<CollectionViewSource x:Key="devicesCollection" IsLiveSortingRequested="True" IsLiveGroupingRequested="True" Source="{Binding MyCollection}">
<!-- Sorting -->
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription PropertyName="Id" />
</CollectionViewSource.SortDescriptions>
<!-- Grouping -->
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="City"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<DataTemplate x:Key="GroupingHeader">
<Border Background="Gray">
<TextBlock Margin="10 5 5 5" FontSize="12" FontWeight="Bold" Text="{Binding Name}"/>
</Border>
</DataTemplate>
<!-- data grid -->
<DataGrid ItemsSource="{Binding Source={StaticResource ResourceKey=devicesCollection}, Mode=OneWay}">
<DataGrid.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource ResourceKey=GroupingHeader}" />
</DataGrid.GroupStyle>
</DataGrid>
Hello Stackoverflowers,
I'm using an ItemsControl and my elements are all drawn on the top left corner, which create to a gap between the actual position and the mouse position (where my elements should be). Relevant mouse positions are saved in view model.
<ItemsControl
ItemsSource="{Binding OverlayElementsList}"
Background="Transparent"
BorderBrush="Black"
BorderThickness="2">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding ElementName=X, Path=Client.OverlayElement.StartPoint}" />
<Setter Property="Canvas.Top" Value="{Binding ElementName=Y, Path=Client.OverlayElement.StartPoint}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type elements:OverlayElement}">
<ContentControl Content="{Binding View}" />
</DataTemplate>
</ItemsControl.Resources>
Here is one of the possible View binded in the ItemsControl.Resources :
<UserControl x:Class="Client.ImageOverlayElementView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Genetec.CS.OverlayModule.Client"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:ImageOverlayElement}">
<Grid>
<Image
Source="{Binding ImageSource}"
Height="{Binding Height}"
Width="{Binding Width}"
Canvas.Left="{Binding StartPoint}"
Canvas.Top="{Binding EndPoint}"/>
</Grid>
</UserControl>
The Canvas.Left and Canvas.Top properties seem to be simply ignored, why ?
I have the following XAML (simplified):
<Grid>
<Popup Name="Popup" DataContext="{Binding ElementName=GameWheel, Path=SelectedItem}" PlacementTarget="{Binding SelectedItem}" Placement="Center" IsOpen="True">
<Image Source="{Binding ImagePath}" Width="100" />
</Popup>
<DockPanel Margin="40,0">
<ListBox x:Name="GameWheel" ...>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<c:VirtualizingWrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Image x:Name="GamesWheelImage" ... />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Grid>
While the DataContext is correct and it shows me the right image in the popup, the placement is completely wrong. My intention is to have the popup cover the center of the SelectedItem in the listbox, but for some reason it's always placed in the center of the window.
Any ideas on how to get the placement for the selectedItem in the listbox so the popup always covers the center of the selected item? The closest I get it to place the image in the center of the listbox, but I'm not able to get it to cover just the selected item.
In my opinion you should create a specific template for the ListBoxItems which belong to the Listbox called GameWheel.
Just to give you a sample, I created a simplier version of your ListBox:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="300" Width="400">
<Window.Resources>
<ControlTemplate x:Key="ListBoxItemWithPopup" TargetType="{x:Type ListBoxItem}">
<Border Name="border" Padding="2">
<Grid>
<Popup Name="popup" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Placement="Center" >
<TextBlock Margin="1" Background="White" Foreground="Black" Text="{TemplateBinding Content}" />
</Popup>
<ContentPresenter />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="popup" Property="IsOpen" Value="True"/>
<Setter TargetName="border" Property="Background" Value="Azure" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Grid>
<DockPanel Margin="40,0">
<ListBox x:Name="GameWheel">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template" Value="{StaticResource ListBoxItemWithPopup}" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
<sys:String>One</sys:String>
<sys:String>Two</sys:String>
<sys:String>Three</sys:String>
<sys:String>Four</sys:String>
</ListBox.Items>
</ListBox>
</DockPanel>
</Grid>
</Window>
As you can see the Popup is directly contained in the ListBoxItem template and it is showed using a Trigger.
I hope my sample can help you.
I have CanContentScroll property set to True in the parent Scrollviewer. This ScrollViewer is applicable to the entire Window. Now, this ScrollViewer has ItemsControl as its child. Each item in the ItemsControl is templated as an Expander and the content of this Expander contains another ItemsControl embedded in the child ScrollViewer. If I remove the child ScrollViewer, the Window content is scrollable, however, if I put it back in, I'm unable to Scroll.
I need the child ScrollViewer because I am limiting the height of the Expander content. When I scroll, the event is not being fired to the parent ScrollViewer in the Visual Tree. How and by using which event I can bubble it to the parent ScrollViewer in the Visual Tree?
This is my code:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="clr-namespace:AttributeSelector" xmlns:sys="clr-namespace:System;assembly=mscorlib"
MinHeight="350" MinWidth="525" MaxWidth="1200" MaxHeight="900" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight">
<sys:Boolean x:Key="BooleanTrue">True</sys:Boolean>
<sys:Boolean x:Key="BooleanFalse">False</sys:Boolean>
<behaviors:TextToHighlightedTextBlockConverter x:Key="TextToHighlightedTextBlockConverter" />
<behaviors:GroupNameToICollectionViewConverter x:Key="GroupNameToICollectionViewConverter" />
<LinearGradientBrush x:Key="LinearGradientBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#E3E3E3" Offset="1"/>
<!--<GradientStop Color="#C0C0C0" Offset="1"/>-->
</LinearGradientBrush>
<Style x:Key="MainBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Background" Value="{StaticResource ResourceKey=LinearGradientBrush}" />
<Setter Property="BorderBrush" Value="LightGray" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="SnapsToDevicePixels" Value="True" />
</Style>
</Window.Resources>
<DockPanel LastChildFill="True" Margin="10">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
<!-- 3-4 TextBlocks/TextBoxes defined here -->
</StackPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" CanContentScroll="True">
<ItemsControl ItemsSource="{Binding UniqueGroups}" ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="5" Style="{StaticResource ResourceKey=MainBorderStyle}">
<Expander x:Name="GroupExpander" Header="{Binding}" IsExpanded="True" Margin="5">
<Expander.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Background="Transparent" Margin="10,0,0,0"
FontWeight="DemiBold" FontSize="16" FontStretch="Expanded"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Expander}}, Path=ActualWidth}"/>
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.Content>
<ScrollViewer Margin="20,5,10,5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" CanContentScroll="True">
<ItemsControl ItemsSource={Binding SubItems} ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel MaxHeight="300" Orientation="Vertical" UseLayoutRounding="True" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
</ScrollViewer>
</Expander.Content>
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>