【问题标题】:WPF - Binding class with Lists of strings to a ListBoxWPF - 将带有字符串列表的类绑定到 ListBox
【发布时间】:2015-06-29 17:17:50
【问题描述】:

我在将多个列表绑定到一个列表框时遇到问题。我希望每个 List 都有一个不同颜色的不同 DataTemplate。

我有以下模型类

public class Users
{
        public Members Members{ get; set; }
}

public class Members
{
        public List<string> Moderators { get; set; }
        public List<string> Viewers { get; set; }
}

我使用 INotifyPropertyChanged 关注 ViewModel

private Users users;

public Users Users
{
    get { return users; }
    set
    {
        users= value;
        RaisePropertyChanged("Users");
    }
}

我正在绑定到这个 ListBox

<ListBox ItemsSource="{Binding Users.Members.Viewers}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
 </ListBox>

现在我只有一个 List 绑定到 ListBox。它工作得很好,但我希望另一个列表也绑定到同一个 ListBox。除此之外,我希望版主有不同的模板。

我尝试了许多不同的方法,但似乎没有任何效果。

【问题讨论】:

    标签: c# wpf xaml listbox


    【解决方案1】:

    与其从原始对象中删除名称,为什么不保留它并根据原始类指定不同的颜色呢?

    此外,我希望版主有不同的模板。

    如果你只有不可能的字符串。请记住,列表框最终只能看到一个列表;所以在一个列表中,如何标记一个字符串作为主持人或查看者?

    具有不同颜色的不同 DataTemplate。

    如果只有字符串,我建议您创建包装类,一个用于主持人,一个用于查看者,然后将字符串投影到要保存的这些类中。然后你可以按照我的建议/示例如下。


    通过使用 Composite 集合来保存不同的项目(或者,如果实例具有这种共性,实际上可以使用基类列表或接口列表),然后有专门的数据模板,看起来对于原始类,可以做到。

    示例

    我有两个班级,一个名为Ships,一个名为Passage。请注意,这两个类都具有 Name 属性,但可以在模板中使用 Name 以外的其他属性。

    下面我定义了数据模板和我的列表框。

    <Grid>
        <Grid.Resources>
            <DataTemplate DataType="{x:Type c:Ship}">
                <TextBlock Text="{Binding Path=Name}"
                            Foreground="Red" />
            </DataTemplate>
            <DataTemplate DataType="{x:Type c:Passage}">
                <TextBlock Text="{Binding Path=Name}"
                            Foreground="Blue" />
            </DataTemplate>
        </Grid.Resources>
        <ListBox Name="myListBox"
                    Height="300"
                    Width="200"
                    ItemsSource="{Binding MyCompositeCollection}">
        </ListBox>
    </Grid>
    

    所以会发生什么,我的船将是红色的,而通道将是蓝色的。


    这是我在虚拟机中的代码:

    private CompositeCollection _MyCompositeCollection;
    
    public CompositeCollection MyCompositeCollection
    {
        get { return _MyCompositeCollection; }
        set { _MyCompositeCollection = value; OnPropertyChanged("MyCompositeCollection"); }
    }
    

    这里我加载复合集合:

    var temp  = new CompositeCollection();
    
    Ships.ForEach(sh => temp.Add(sh));
    Passages.ForEach(ps => temp.Add(ps));
    
    MyCompositeCollection = temp;
    

    【讨论】:

    • 很好的解释!我没有提到我无法更改示例中提到的类,因为我从 WebAPI 中“继承”了它们。但我当然可以从字符串 Lists 中创建新类。
    • @Shamshiel 不要忘记可以拥有Partial 类,而WebAPI 类实际上可以根据需要扩展属性。
    【解决方案2】:
    1. 为了组合两个列表并将其设置为 ItemsSource,请使用 CompositeCollection
    2. WPF 可以使用 ItemTemplateSelector 设置不同的模板,但它需要类在某些方面是不同的。您的类型是字符串,因此它没有任何不同。我的提示是按如下方式创建枚举

      枚举成员类型 { 主持人, 查看器 }


    和以下课程:

    class Person
    {
        public string Name{get;set;}
        public MemberType Type{get;set;}
    }
    

    然后改成这个

    public class Members
        {
            public List<Person> Moderators { get; set; }
            public List<Person> Viewers { get; set; }
        }
    

    最终在ItemTemplateSelector

      public class TemplateSelector : DataTemplateSelector
        {
            public DataTemplate ViewerDataTemplate;
            public DataTemplate ModeratorDataTemplate;
    
            public override DataTemplate SelectTemplate(object item, DependencyObject container)
            {
                var member = item as Person;
                switch (member.Type)
                {
                    case MemberType.Moderator:
                        return ModeratorDataTemplate;
                    case MemberType.Viewer:
                        return ViewerDataTemplate;
                }
    
                return null;
            }
        }
    

    【讨论】:

    • 有趣的想法。可能需要添加一件事,例如展示如何将TemplateSelector连接到 Xaml 中的 ListBox 中。
    • 我指出了诸如 TemplateSelector 之类的关键字。您可以在 SO 上查找的所有内容。如果已经存在此类示例,我想避免复制和粘贴。
    • 感谢您的回答。遗憾的是,我只能将其中一个答案标记为正确。
    猜你喜欢
    • 1970-01-01
    • 2012-03-12
    • 2011-02-01
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 2012-06-20
    • 1970-01-01
    相关资源
    最近更新 更多