【问题标题】:Binding ListView field to a nested list WPF将 ListView 字段绑定到嵌套列表 WPF
【发布时间】:2018-03-20 17:56:23
【问题描述】:

我有以下课程:

class Event {
int eserc {get;set;}
int type {get;set;}
}

class Sequence {
List<Event> events;
int freq {get;set;}
}

如您所见,我有一个序列内的事件列表。我有一个序列列表。
我想显示一个带有序列列表的 GridViewListView。对于每个序列,我希望有 2 列,其中一列具有属性 freq 的值,另一列应具有与该序列关联的事件列表。例如:
其中第一行与第一个序列有关。矩形的颜色代表事件的类型。在第一个序列中有以下事件:

  • “红色”类型的 eserc 1
  • “红色”类型的 eserc 2
  • “绿色”类型的 eserc 3
  • “红色”类型的 eserc 4

我知道我必须进行绑定以显示值,但我不知道如何对序列进行绑定,因为我应该将列的值绑定到 Event 的值 每个单个 Sequence 中的对象。
这是我为 ListView 编写的代码:

<ListView Name="resultsList" Grid.Row="5" Grid.Column="1"
                  Grid.ColumnSpan="3">
    <ListView.View>
                <GridView>

            <GridViewColumn Header="Sequence" Width="450"
                                    DisplayMemberBinding="{Binding events}"/>
            <GridViewColumn Header="Frequence" 
                                    DisplayMemberBinding="{Binding freq}"/>
        </GridView>
    </ListView.View>
</ListView>

当然,Binding events 是错误的,因为只有当它是一个字符串时才会起作用,但这就是想法。
我在互联网上搜索,我认为我应该使用 DataTemplate 之类的东西,但我不确定,我不太了解它是如何工作的。我知道当源是一个对象时它可以工作,但在这种情况下它是一个对象的List,我不知道如何获取信息。

【问题讨论】:

  • 使用 DataTemplate 在第一列的单元格中显示嵌套列表(阅读 GridViewColumn.CellTemplate 的文档,有关使用 CellTemplate 属性的示例,请参见此处:stackoverflow.com/questions/4725352/…
  • 哦,您可以使用 DataTrigger 实现的着色根据 DataTrigger 绑定到的属性的值改变颜色 (wpf-tutorial.com/styles/trigger-datatrigger-event-trigger)
  • 最后,+1 表示您问题的出色表现,包括一个涂鸦,让您可以轻松理解您的目标是什么。希望人们会更多地支持格式良好的问题,而不仅仅是反对写得不好、费力的问题。
  • 我只记得我忘了添加一件事:“我知道当源是一个对象时它可以工作,但在这种情况下它是一个对象列表,我不知道如何获取信息。”。哦,你已经知道了。看,您已经知道如何使用 ListBox/ListView 显示 List:。那么,您将如何在列单元格中显示您的 List ?是的,你猜对了;再次,使用 ListBox/ListView... ;-)
  • 有多少项目可以包含events

标签: c# wpf listview data-binding


【解决方案1】:

要实现这一点,您需要在第一个 GridViewColumn 内定义另一个列表,该列表应该是水平的(编辑 ItemsPanelTemplate)。您可以使用 ListViewListBoxItemsControl(看起来最合适)。

要根据Event 的类型绘制不同颜色的Border,您应该首先为ItemsControl 项目定义一个自定义DataTemplate,并使用DataTrigger 设置颜色,这里是完整的 xaml:

<ListView Name="ResultsList" 
             ItemsSource="{Binding SequenceCollection}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Sequence" Width="450" >
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ItemsControl ItemsSource="{Binding Events}">
                                <ItemsControl.ItemsPanel>
                                   <ItemsPanelTemplate>
                                       <StackPanel Orientation="Horizontal"></StackPanel>
                                   </ItemsPanelTemplate>
                               </ItemsControl.ItemsPanel>
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Border>
                                            <Border.Style>
                                                <Style TargetType="Border">
                                                    <Style.Triggers>
                                                        <DataTrigger Binding="{Binding Type}" Value="red">
                                                            <Setter Property="Background" Value="red"/>
                                                        </DataTrigger>
                                                        <DataTrigger Binding="{Binding Type}" Value="green">
                                                            <Setter Property="Background" Value="Green"/>
                                                        </DataTrigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </Border.Style>
                                            <TextBlock Text="{Binding Eserc, StringFormat='{}{0} '}"></TextBlock>
                                        </Border>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Frequence" 
                                DisplayMemberBinding="{Binding Freq}"/>
            </GridView>
        </ListView.View>
    </ListView>

序列集合:

    private ObservableCollection<Sequence> _sequenceCollection =new ObservableCollection<Sequence>()
    {
        new Sequence(){Events = new ObservableCollection<Event>()
        {
            new Event(){Eserc=1, Type = "red"},
            new Event(){Eserc=2, Type = "red"},
            new Event(){Eserc=3, Type = "green"},
            new Event(){Eserc=4, Type = "red"},
        },Freq = 3}
    };
    public ObservableCollection<Sequence> SequenceCollection
    {
        get { return _sequenceCollection; }
        set
        {
            if (Equals(value, _sequenceCollection)) return;
            _sequenceCollection = value;
            OnPropertyChanged();
        }
    }

这里是你需要邻接的类:

public class Event
{
    public int Eserc { get; set; }
    public string Type { get; set; }
}

public class Sequence
{
    public ObservableCollection<Event> Events { get; set; }
    public int Freq { get; set; }
}

输出:

侧面:

  1. 确保定义公共属性以便能够正确绑定它们
  2. 使用命名约定
  3. 使用ObservableCollection 而不是List(他们实现ICollectionChanged,这对于更改通知很方便)
  4. 别忘了实现INotifyPropertyChanged 接口

【讨论】:

  • 哇!谢谢您的回答!我试图实现它,但我遇到了一些问题。首先,它给了我一个关于 SequenceCollection 属性定义的错误,说“属性的类型 'ObservableCollection 比属性”结果更难访问。 SequenceCollection”(其中 Results 是包含 SequenceCollection 的窗口的类)。
  • 另一件事,在 OnPropertyChanged() 方法中实现 INotifyPropertyChanged 接口我必须做什么? (我在结果类中做到了)
  • 关于第一个问题,只要确保该属性是公开的。对于通知更改,只要您希望属性上的更改反映在 ui 上,请在属性中调用 onepropertychanged()。
  • 非常感谢您的帮助!使用整个代码我解决了问题!谢谢你的耐心:)
  • 这是功能齐全的源代码最有用的答案。非常好。 +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
  • 2013-12-06
  • 1970-01-01
  • 1970-01-01
  • 2017-10-26
相关资源
最近更新 更多