【问题标题】:Flatten groups in CollectionViewSourceCollectionViewSource 中的展平组
【发布时间】:2016-08-27 13:40:22
【问题描述】:

我需要计算ObservableCollection 中可用的联赛。问题是联赛名称重复,所以我需要删除重复项。其实我是这样的:

private static ObservableCollection<Models.Event> _matches = new ObservableCollection<Models.Event>();

public ObservableCollection<Models.Event> Matches
{
    get { return _matches; }
}

基本上我有一系列赛事,现在每个赛事都有一个关联的联赛。我的想法是创建另一个名为 LeaguesCount 的属性:

public int LeaguesCount
{
   //remove duplicate record from _matches here
}

并返回可用的联赛,但还有另一个问题。因为每个联赛都不一样,所以我可以:

Premier League x3
Serie A x5
Super League x4
...

我需要将计数分开。注意到这个联盟在国家名称中是关联的,所以我可以在_matches 有两个具有这种结构的事件:

事件 (1)

match_name = 'Foo';
match_nation = 'England';
match_league = 'Premier League';

事件(2)

match_name = 'Test';
match_nation = 'England';
match_league = 'Premier League';

事件(3)

match_name = 'Another event';
match_nation = 'England';
match_league = 'Championship';

所以您如何在England 国家/地区看到三个具有Premier League 联赛名称和Championship 联赛名称的赛事,我需要从国家England 获得所有联赛的计数,当然避免重复。

事件的结构基本上是这样的:

public class Event : ViewModel
{
     private string _matchNation,
                    _matchLeague,
                    _matchName;
}

每个字段都有一个关联的属性。与此问题相关的属性是:

public string MatchNation
    {
        get { return _matchNation; }
        set
        {
            _matchNation = value;
            OnPropertyChanged();
        }
    }
    public string MatchLeague
    {
        get { return _matchLeague; }
        set
        {
            _matchLeague = value;
            OnPropertyChanged();
        }
    }
    public string MatchName
    {
        get { return _matchName; }
        set
        {
            _matchName = value;
            OnPropertyChanged();
        }
    }

想要的结果:

England -> League count (2) [Championship, Premier League]

主要问题是不同的国家名称,因为我在 xaml 中绑定源是这样的:

<CollectionViewSource Source="{Binding Matches}" x:Key="GroupedItems">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="MatchNation" />
            </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

GroupHeaderTemplate:

<TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="White" FontSize="22" VerticalAlignment="Bottom" />
                                                            <TextBlock Text="{Binding ItemCount}" FontSize="22" Foreground="Orange" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />

ItemCount 实际上返回所有项目计数(事件)而不是没有重复的联赛,这是一个错误。

【问题讨论】:

  • 我认为您要么打错字,要么有逻辑问题。您按MatchNation 分组 -> 只有 England 所以结果 (3) 是正确的。你应该改为MatchLeague
  • @lok​​usking 不是一个合乎逻辑的问题,我需要将活动分组为国家,所以在我的组描述中我有这个组织:Nations-&gt;Leagues-&gt;Events。现在我需要计算所有国家的联赛数量(不重复)。我不知道有什么不清楚的地方,请告诉我,我会尽力解释得更好,谢谢。

标签: c# wpf


【解决方案1】:

你真的让我有点头疼。 不幸的是,您的模型不适合执行此操作。我对它们做了一些修改(我懒得到处实现INotifyPropertyChanged):

模型

 public class Country {

        public Country() {
            this.Leagues = new ObservableCollection<League>();
        }
        public string Name { get; set; }

        public ObservableCollection<League> Leagues { get; }

    }

    public class League {

        public League() {
            this.Events = new ObservableCollection<Event>();
        }
        public string Name { get; set; }

        public ObservableCollection<Event> Events { get; }
    }

    public class Event : INotifyPropertyChanged {
        private string _matchName;
        public string MatchName {
            get { return _matchName; }
            set {
                _matchName = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        }
    }

带有演示数据的 ViewModel

public partial class VM {

        public VM() {
            var eng = new Country() {Name = "England"};
            var l1 = new League() {Name = "Championship" };
            l1.Events.Add(new Event() {MatchName = "Another event" });
            var l2 = new League() { Name = "Premier League" };
            l2.Events.Add(new Event() { MatchName = "Foo" });
            l2.Events.Add(new Event() { MatchName = "Bar" });
            eng.Leagues.Add(l1);
            eng.Leagues.Add(l2);
            this.Countries.Add(eng);
            
        }

        private ObservableCollection<Country> _countries = new ObservableCollection<Country>();

        public ObservableCollection<Country> Countries {
            get { return _countries; }
        }

    }

CollectionViewSource

<CollectionViewSource Source="{Binding Countries}" x:Key="GroupedItems">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="Name" />
            </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

列表视图

<ListView ItemsSource="{Binding Source={StaticResource GroupedItems}}">
        <ListView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <WrapPanel DataContext="{Binding Items}">
                            <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="22" VerticalAlignment="Bottom" />
                            <TextBlock Text="->" Margin="10,0,0,0" FontWeight="Bold" FontSize="22" VerticalAlignment="Bottom"/>
                            <TextBlock Text="League count" Margin="10,0,0,0" FontWeight="Bold" FontSize="22" VerticalAlignment="Bottom"/>
                            <TextBlock Text="{Binding Leagues.Count}" FontWeight="Bold" FontSize="22" VerticalAlignment="Bottom" Margin="10,0,0,0" />
                            <ItemsControl ItemsSource="{Binding Leagues}">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Name}" FontSize="22" Foreground="Orange" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <WrapPanel></WrapPanel>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                            </ItemsControl>
                        </WrapPanel>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </ListView.GroupStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel DataContext="{Binding Leagues}">
                    <ItemsControl ItemsSource="{Binding}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Name}"></TextBlock>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>

                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

结果

注意

如您所见,您的 Groupheader 下方显示的项目可以修改(标记为黄色)。 为此,您必须每次更改面板的DataContext(我很确定,没有其他办法)。

关闭

不漂亮但工作。您可能需要使用 XAML 才能满足您的需求

【讨论】:

  • 感谢您的回答。这解决了我想我实际上尝试了代码的问题。当然,我需要在我的结构中更改很多逻辑。再次感谢,很抱歉让你头疼:)
  • 只是一个问题:可以将联赛设置为属性组描述吗?在你的新逻辑中,联赛是一个可观察的集合,我如何在第二个属性组描述中绑定联赛?
  • @AgainMe 当然可以。但结果可能会有所不同
  • 我在这里开了一个新问题:stackoverflow.com/questions/39189278/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-03
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 2017-04-06
  • 1970-01-01
相关资源
最近更新 更多