【问题标题】:Not able to organize data in DropDownButton无法在 DropDownButton 中组织数据
【发布时间】:2016-10-10 07:28:29
【问题描述】:

总结

我有一个DropDownButton,其中包含特定国家的所有联赛。因此,基本上用户从ComboBox 中选择Nation,所选NationLeagues 将添加到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&lt;T&gt; 可用并且如果被选中。为了使它在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

所以基本上我为CheckedListItemItemSourceGroupedData 添加了一个模板,你可以从上面的代码中看到如何绑定ObservableCollectionLeagues

数据人口

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();
    }
}

添加所选LeagueLeague 调用的方法是这样的:

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);
        }
    });
}

基本上我创建了一个CheckedListItemCheckedListItem 作为模型包含此属性:

public class League
{
    public string Name { get; set; }
    public string Link { get; set; }
    public string Country { get; set; }
}

应该出现的结果是这样的:

拍摄from this tutorial

但是我得到了这个结果:

如您所见,我没有带有 Nation 名称的标题分组。我在 XAML 或代码中也没有错误,所以我不知道为什么标题没有出现。

我知道这个问题可能有点复杂,所以有任何问题或更多细节可以问我,我会尽力回答。

演示解决方案:

https://mega.nz/#!g4YlTL4A!G4WXy1t64Q4yImYNvzgwGbieX1mhKnXO2OiuAO3FDg0

【问题讨论】:

  • 我这里没有 MahApp,但在这种情况下我通常会为各种元素添加不同的背景颜色。这样可以更轻松地查看正在显示的模板和元素。
  • @PieterWitvoet 问题出在combinedTemplate 上,在分组中不起作用。
  • 好像是this question的副本。

标签: c# wpf xaml mahapps.metro


【解决方案1】:

我不会尝试让第三方控制工作,而是更改工作 ComboBox 以满足您的需求:

MainWindow.xaml

<Controls:MetroWindow x:Class="WpfApplication1.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:Controls="http://metro.mahapps.com/winfx/xaml/controls"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="700" Width="525">
    <Window.Resources>
        <ResourceDictionary>

            <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>

            <Style TargetType="{x:Type GroupItem}" x:Key="containerStyle">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type GroupItem}">
                            <Expander   IsExpanded="False" x:Name="ComboExpander" Header="{TemplateBinding Content}"
                                        HeaderTemplate="{StaticResource GroupHeader}">
                                <ItemsPresenter />
                            </Expander>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

            <DataTemplate x:Key="NormalItemTemplate">
                <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item.Name}" x:Name="Leagues" />
            </DataTemplate>
            <DataTemplate x:Key="HeaderTemplate">
                <TextBlock Text="Campionati"/>
            </DataTemplate>
            <DataTemplate x:Key="CombinedTemplate">
                <ContentPresenter x:Name="Presenter" 
                   Content="{Binding}"
                   ContentTemplate="{StaticResource NormalItemTemplate}" />
                <DataTemplate.Triggers>
                    <DataTrigger
                        Binding="{Binding RelativeSource={RelativeSource FindAncestor, ComboBoxItem, 1}}"
                        Value="{x:Null}">
                        <Setter TargetName="Presenter" Property="ContentTemplate"
                            Value="{StaticResource HeaderTemplate}" />
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ResourceDictionary>

    </Window.Resources>    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ComboBox x:Name="LeagueMenuComboBox" 
                  ItemsSource="{Binding Source={StaticResource GroupedData}}"
                  ItemTemplate="{StaticResource CombinedTemplate}"
                  HorizontalContentAlignment="Center">
            <ComboBox.GroupStyle>
                <GroupStyle ContainerStyle="{StaticResource containerStyle}"
                            HeaderTemplate="{StaticResource GroupHeader}">
                </GroupStyle>
            </ComboBox.GroupStyle>
        </ComboBox>
    </Grid>
</Controls:MetroWindow>

【讨论】:

  • 感谢您付出的时间。在接受您的回答之前我有几个问题: 1. 是否可以在组合框中独立于所选项目设置默认文本? 2. 可以改变 GroupBox 文本的颜色(我的意思是国家名称颜色)吗?谢谢。
  • @AgainMe 不客气,回答您的问题: 1. 这就是CombinedTemplate 的用途,它确保默认文本无论如何都保持不变。 2.将GroupHeader内容设置为:&lt;TextBlock Text="{Binding Name}" Margin="10,0,0,0" Foreground="Blue"/&gt;
  • 谢谢,我需要等待 stackoverflow 时间限制才能向您发送赏金。只有一件事:不幸的是,我没有在组合框中显示默认文本..
  • @AgainMe 默认文本在HeaderTemplate 中设置。请注意,DataTrigger 绑定中的祖先现在是 ComboBoxItem 类型(而不是 DropDownButton)。如果这无济于事,请尝试用我发布的代码替换链接项目中的 xaml 文件。
  • 我明白为什么不工作了。因此,当我启动应用程序时,我的 ComboBox 上没有文本,如果我检查一个项目,同样的情况,只有当我在组合框中选择项目本身时才会出现文本。应用程序运行时不能保留文本吗?我虽然设置 selectedindex = 0 来解决这个问题,但也许你知道另一种解决方案。
猜你喜欢
  • 2017-02-17
  • 1970-01-01
  • 2023-01-04
  • 1970-01-01
  • 2021-11-28
  • 2013-12-14
  • 2020-09-16
  • 2022-01-02
  • 2013-04-29
相关资源
最近更新 更多