Summary
I've a DropDownButton
that contains all leagues of a specific nations. So essentially the user select a Nation
from a ComboBox
and the Leagues
of the selected Nation
will be added inside the DropDownButton
. Until here no problem.
What I need to do is: organize the Leagues
inside the DropDownButton
for Nation
. So imagine that inside the DropDownButton
I've this organization:
Italy
Item1
Item2
Item3
England
Item1
Item2
Spain
Item1
Item2
... etc ...
Item type
How you can see the item are organized by nation. Before explain what I did for achieve this result I have to say that I'm using a CheckedListItem
class, that is essentially a class that bind a CheckBox
to the item of the DropDownButton
. This class is pretty simple:
public class CheckedListItem<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool isChecked;
private T item;
public CheckedListItem() { }
public CheckedListItem(T item, bool isChecked = false)
{
this.item = item;
this.isChecked = isChecked;
}
public T Item
{
get { return item; }
set
{
item = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item"));
}
}
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsChecked"));
}
}
}
Essentially make available the Item<T>
and if is selected. For make this working in XAML
I wrote this code in the Window.Resources
:
<DataTemplate x:Key="NormalItemTemplate">
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item.Name}"
x:Name="Leagues" Checked="Leagues_Checked" Unchecked="Leagues_Unchecked" />
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate" >
<TextBlock Text="{DynamicResource displayedNation}"/>
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter" Content="{Binding}" ContentTemplate="{StaticResource NormalItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, Controls:DropDownButton, 1}}"
Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate"
Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<!--This is for the group item !-->
<Style TargetType="{x:Type GroupItem}" x:Key="containerStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<!--Here, we tell that each group of item will be placed under Expander control,
and this expander control will by default will have style we defined in above code.-->
<Expander IsExpanded="False" x:Name="ComboExpander" Header="{TemplateBinding Content}"
HeaderTemplate="{TemplateBinding ContentTemplate}">
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Explain the problem
Now for achieve the grouping in the DropDownButton
I've created first a CollectionViewSource
in the Window.Resource
like this:
<CollectionViewSource Source="{Binding Leagues}" x:Key="GroupedData">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Item.Country" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<DataTemplate x:Key="GroupHeader">
<TextBlock Text="{Binding Name}" Margin="10,0,0,0" Foreground="#989791"/>
</DataTemplate>
in the DropDownButton
I set this structure:
<Controls:DropDownButton Content="Leagues" x:Name="LeagueMenu"
ItemsSource="{Binding Source={StaticResource GroupedData}}"
ItemTemplate="{StaticResource CombinedTemplate}" >
<Controls:DropDownButton.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource containerStyle}"
HeaderTemplate="{StaticResource GroupHeader}">
</GroupStyle>
</Controls:DropDownButton.GroupStyle>
</Controls:DropDownButton>
(Please, note that I'm using MahApp)
So essentially I added a template for the CheckedListItem
and as ItemSource
the GroupedData
that how you can see from code above bind the ObservableCollection
of Leagues
.
Data population
When a Nation
is selected a list of Leagues
available for the selected Nations
will be added in the DropDownButton
, the code for achieve this:
private ObservableCollection<CheckedListItem<League>> _leagues = new ObservableCollection<CheckedListItem<League>>();
public ObservableCollection<CheckedListItem<League>> Leagues
{
get
{
return _leagues;
}
set
{
_leagues = value;
OnPropertyChanged();
}
}
the method that's called for add the League
of the selected Nation
is this:
public void GetLeagues(string link, string nation)
{
Task.Run(() =>
{
var leagues = //get some collection
foreach (var league in leagues)
{
var championship = new CheckedListItem<League>();
championship.Item = new League { Name = league.Name, Link = league.Link, Country = nation };
_leagues.Add(championship);
}
});
}
Essentially I create a CheckedListItem
of League
that as model contains this property:
public class League
{
public string Name { get; set; }
public string Link { get; set; }
public string Country { get; set; }
}
The result that should be appear is something like this:
Taken from this tutorial.
But instead I get this result:
As you can see I doesn't have the header grouping with the Nation
name. I also get no error in XAML or in code, so I don't know why the header doesn't appear.
I know that the problem could be a bit complicated, so for any question or more details ask me and I'll try to answer.
Demo solution:
https://mega.nz/#!g4YlTL4A!G4WXy1t64Q4yImYNvzgwGbieX1mhKnXO2OiuAO3FDg0