【发布时间】:2016-10-10 07:28:29
【问题描述】:
总结
我有一个DropDownButton,其中包含特定国家的所有联赛。因此,基本上用户从ComboBox 中选择Nation,所选Nation 的Leagues 将添加到DropDownButton 中。直到这里没有问题。
我需要做的是:在DropDownButton 中为Nation 组织Leagues。所以想象一下,在DropDownButton 里面我有这个组织:
Italy
Item1
Item2
Item3
England
Item1
Item2
Spain
Item1
Item2
... etc ...
物品类型
您如何查看项目按国家/地区组织。在解释我为实现此结果所做的工作之前,我必须说我正在使用CheckedListItem 类,它本质上是将CheckBox 绑定到DropDownButton 的项目的类。这个类很简单:
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"));
}
}
}
基本上使Item<T> 可用并且如果被选中。为了使它在XAML 中工作,我在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>
解释问题
现在为了在DropDownButton 中实现分组,我首先在Window.Resource 中创建了一个CollectionViewSource,如下所示:
<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>
在DropDownButton我设置了这个结构:
<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>
(请注意,我使用的是 MahApp)
所以基本上我为CheckedListItem 和ItemSource 和GroupedData 添加了一个模板,你可以从上面的代码中看到如何绑定ObservableCollection 的Leagues。
数据人口
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();
}
}
添加所选League 的League 调用的方法是这样的:
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);
}
});
}
基本上我创建了一个CheckedListItem 的CheckedListItem 作为模型包含此属性:
public class League
{
public string Name { get; set; }
public string Link { get; set; }
public string Country { get; set; }
}
应该出现的结果是这样的:
但是我得到了这个结果:
如您所见,我没有带有 Nation 名称的标题分组。我在 XAML 或代码中也没有错误,所以我不知道为什么标题没有出现。
我知道这个问题可能有点复杂,所以有任何问题或更多细节可以问我,我会尽力回答。
演示解决方案:
https://mega.nz/#!g4YlTL4A!G4WXy1t64Q4yImYNvzgwGbieX1mhKnXO2OiuAO3FDg0
【问题讨论】:
-
我这里没有 MahApp,但在这种情况下我通常会为各种元素添加不同的背景颜色。这样可以更轻松地查看正在显示的模板和元素。
-
@PieterWitvoet 问题出在
combinedTemplate上,在分组中不起作用。 -
好像是this question的副本。
标签: c# wpf xaml mahapps.metro