[英]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 -> Inter
和Serie 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.