繁体   English   中英

无法绑定GridView列中的项目列表

[英]Cannot bind list of items in GridView column

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

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类包含每个事件的属性,尤其是事件的名称,日期等。

我按以下方式评估此数据:

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 -> InterSerie B -> Milan实际上都包含一场比赛

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

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

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

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

<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中编写以下代码:

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

这修复了显示在GroupStyle和GridView中的联赛名称的错误:

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

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

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

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

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属性,例如:

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

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

替代解决方案

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM