无法绑定GridView列中的项目列表 [英] Cannot bind list of items in GridView column

查看:36
本文介绍了无法绑定GridView列中的项目列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个应用程序,向用户显示比赛系列的实时结果.我将数据的结构设置如下: Countries-> Leagues-> Matches 特别是在ViewModel中,我创建了一个可观察到的国家/地区集合,如下所示:

I'm building an application that show to user the live result of a matches series. I setup the structure of data as follows: Countries->Leagues->Matches In particular in the ViewModel I've created an observable collection of countries as follows:

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

public ObservableCollection<Models.Country> Country
{
    get { return _countries; }
}

和模型:

public class Country
{
    public string Name { get; set; }
    public List<League> League { get; set; }
}

public class League
{
    public string Name { get; set; }
    public List<Event> Event { get; set; }
}

Event类包含每个事件的属性,尤其是事件的名称,日期等.

the class Event contains the properties of each event, in particular the name of the event, the date and so on..

我按如下方式评估这些数据:

I valorize this data as follows:

Country country = new Country();
country.Name = "Italy";

League league = new League();
league.Name = "Serie A";
League league2 = new League();
league2.Name = "Serie B";

Event @event = new Event();
@event.MatchHome = "Inter";

Event event2 = new Event();
@event.MatchHome = "Milan";

league.Event = new List<Event>(); 
league2.Event = new List<Event>();

league.Event.Add(@event);
league2.Event.Add(event2);

country.League = new List<League>();

country.League.Add(league);
country.League.Add(league2);

lsVm.Country.Add(country); //lsVm contains the ViewModel

如何查看,我创建了一个名为 country (意大利)的对象,在这种情况下,该对象将包含两个联赛(意甲)和(联赛B).每个联赛实际上在玩 Serie A->中包含一场比赛.Inter Serie B->米兰

How you can see I create an object called country (Italy) that will contains in this case two leagues (Serie A) and (Serie B). Each league contains one match actually in playing Serie A -> Inter and Serie B -> Milan

我将联盟两个国家/地区,最后一个国家/地区添加到视图模型的可观察集合中.到这里为止没有问题.问题出在xaml中.

I add the league two the country, and finally the country to the observable collection in the viewmodel. Until here no problem. The problem's come in the xaml.

因此,我已经在GroupViews中组织了所有这些内容,为此,我正在使用CollectionViewSource,尤其是:

So I've organized all of this stuff inside of GroupViews, for doing this I'm using a CollectionViewSource, in particular:

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

上面的代码位于我的Window.Resources中,并告诉CollectionViewSource为国家名称和联赛名称组织相关的各个联赛.我有两个这样的ListView:

the code above is located in my Window.Resources, and tell to CollectionViewSource to organize for country name and leagues name the respective leagues associated. I've two ListView as this:

<ListView ItemsSource="{Binding Source={StaticResource GroupedItems}}" Name="Playing">
                    <ListView.View>
                        <GridView>
                            <GridViewColumn Header="Date" Width="150" DisplayMemberBinding="{Binding Path = League.Event.MatchDate}"/>
                            <GridViewColumn Header="Minutes" Width="70" DisplayMemberBinding="{Binding Path = League.Event.MatchMinute}"/>
                            <GridViewColumn Header="Home" Width="150" DisplayMemberBinding="{Binding Path = League.Event.MatchHome}"/>
                            <GridViewColumn Header="Score" Width="100" DisplayMemberBinding="{Binding Path = League.Event.MatchScore}"/>
                            <GridViewColumn Header="Away" Width="150" DisplayMemberBinding="{Binding Path = League.Event.MatchAway}"/>
                        </GridView>
                    </ListView.View>
<GroupStyle>
                            <GroupStyle.ContainerStyle>
                                <Style TargetType="{x:Type GroupItem}">
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate>
                                                <Expander IsExpanded="True" Background="#4F4F4F" >
                                                    <Expander.Header>
                                                        <StackPanel Orientation="Horizontal" Height="22">
                                                            <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" />
                                                            <TextBlock Text=" Leagues" FontSize="22" Foreground="White" FontStyle="Italic" VerticalAlignment="Bottom" />
                                                        </StackPanel>
                                                    </Expander.Header>
                                                    <ItemsPresenter />
                                                </Expander>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </GroupStyle.ContainerStyle>
                        </GroupStyle>

GroupStyle包含将包含每个比赛的联赛,现在的问题是我看不到任何联赛和任何比赛,因为此项目在列表中.因此,为了显示它们,我应该在xaml中编写以下代码:

The GroupStyle contains the leagues that will contains each match, now the problem is that I can't see any league and any match 'cause this item are inside of a list. So for display them I should write in the xaml this code:

<PropertyGroupDescription PropertyName="League[0].Name" /> 

此修复了将联赛名称显示在GroupStyle中的错误并在GridView中:

this fix the bug of the league name displayed into GroupStyle and in the GridView:

<GridViewColumn Header="Casa" Width="150" DisplayMemberBinding="{Binding Path = League[0].Event[0].MatchHome}"/>

但是,这当然只会显示特定的项目,而不显示项目列表.我需要帮助来解决这种情况,我无法弄清楚.谢谢.

but this of course will display only the specific item.. not the list of items. I need help to fix this situation, I cannot figure out. Thanks.

推荐答案

如果要使用 ListView 的分组功能,则必须为其提供您想要的项目的简单列表组(在您的情况下是联赛),而不是标题项. CollectionView 通过指定 GroupDescriptions 为您进行分组.

If you want to use the ListView's grouping abilities, you have to provide it a flat list of the items you want to group (in your case, the leagues), not the header items. The CollectionView does the grouping for you by specifying GroupDescriptions.

例如,假设 League 类具有 Country 属性:

For example, assuming the League class has a Country property:

class ViewModel
{
    public ObservableCollection<Models.Country> Country { get; }

    public IEnumerable<League> AllLeagues => Country.SelectMany(c => c.Leagues);
}

public class League
{
    public string Name { get; set; }
    public List<Event> Event { get; set; }
    // add Country here
    public Country Country { get; set; }
}

class 

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

然后,当您绑定列时,直接绑定到 League 属性,例如:

Then when you bind the columns, you bind directly to League properties, e.g.:

<GridViewColumn Header="Date" DisplayMemberBinding="{Binding Path=Event.MatchDate}"/>

并且按照组的样式,您可以绑定到 Country 属性,

And in the group style you can bind to Country properties, as you've done.

如果要在WPF中显示任何分层数据,则可以使用为其构建的控件(例如Xceed数据网格),也可以将其与内置WPF数据网格的行详细信息一起修改.

If you want to display any hierarchical data in WPF you can either use a control that was built for it (such as the Xceed data grid) or hack it together with the built-in WPF data grid's row details.

这是一个示例XAML(请注意,它使用了您的原始数据结构,没有我上面建议的修改).这些实际上是彼此嵌套的3个数据网格.每个网格都有自己的一组列,因此您可以为每个级别定义任何内容(国家,联赛,赛事).

Here's a sample XAML for this (note it uses your original data structures without the modifications I suggested above). These are essentially 3 data grids nested within each other. Each grid has its own set of columns, so you can define anything you want for each level (Country, League, Event).

<Window x:Class="WpfApp.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"
        mc:Ignorable="d"
        xmlns:app="clr-namespace:WpfApp"
        d:DataContext="{d:DesignData ViewModel}">
    <FrameworkElement.Resources>
        <app:VisibilityToBooleanConverter x:Key="VisibilityToBooleanConverter" />
        <DataTemplate x:Key="HeaderTemplate">
            <Expander IsExpanded="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridRow}, Path=DetailsVisibility, Converter={StaticResource VisibilityToBooleanConverter}}" />
        </DataTemplate>
        <Style x:Key="DataGridStyle"
               TargetType="DataGrid">
            <Setter Property="RowHeaderTemplate"
                    Value="{StaticResource HeaderTemplate}" />
            <Setter Property="RowDetailsVisibilityMode"
                    Value="Collapsed" />
            <Setter Property="AutoGenerateColumns"
                    Value="False" />
            <Setter Property="IsReadOnly"
                    Value="True" />
        </Style>
    </FrameworkElement.Resources>
    <Grid>
        <DataGrid ItemsSource="{Binding Country}"
                  Style="{StaticResource DataGridStyle}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name"
                                    Binding="{Binding Name}" />
            </DataGrid.Columns>
            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <DataGrid ItemsSource="{Binding League}"
                              Style="{StaticResource DataGridStyle}">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Name"
                                                Binding="{Binding Name}" />
                        </DataGrid.Columns>
                        <DataGrid.RowDetailsTemplate>
                            <DataTemplate>
                                <DataGrid ItemsSource="{Binding Event}"
                                          AutoGenerateColumns="False"
                                          IsReadOnly="True">
                                    <DataGrid.Columns>
                                        <DataGridTextColumn Header="Match Home"
                                                            Binding="{Binding MatchHome}" />
                                    </DataGrid.Columns>
                                </DataGrid>
                            </DataTemplate>
                        </DataGrid.RowDetailsTemplate>
                    </DataGrid>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>
    </Grid>
</Window>

您还需要我使用的转换器的代码:

You'll also need the code for the converter I used:

public class VisibilityToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        => value as Visibility? == Visibility.Visible;

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => value as bool? == true ? Visibility.Visible : Visibility.Collapsed;
}

这篇关于无法绑定GridView列中的项目列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆