如何在列表框中显示多个词典项目 [英] How to show multiple Dictionary items in ListBox

查看:69
本文介绍了如何在列表框中显示多个词典项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码有两个ListBox(LeftListBoxRightListBox)和一个TextBox.这些列表框在它们之间传输项目.文本框显示一个数字,该数字与RightListBox中的SelectedItem相对应(例如,选择T1时显示10,选择T2时显示20,依此类推).

My code has two ListBoxes (LeftListBox and RightListBox) and one TextBox. Those ListBoxes transfer the items between the them. The TextBox shows a number, which corresponds to the SelectedItem in RightListBox (e.g., when T1 is selected, it shows 10, when T2 is selected, it shows 20, and so on).

我刚刚做到了!! ...但是那些列表框只显示三分之一中的第一个词典项 ...我该如何显示所有这些?

I've just made it!! ... but those ListBoxes show only the 1st Dictionary item out of three ... How can I show all of them?

这是我的代码:

MainWindow.xaml

MainWindow.xaml

<Window x:Class="ListBoxMoveAll.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"
        xmlns:local="clr-namespace:ListBoxMoveAll"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="600">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="80" />
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="2*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ListBox x:Name="LeftListBox" Grid.Row="0" Grid.RowSpan="3" Grid.Column="0"
            ItemsSource="{Binding LeftListBoxItems}" DisplayMemberPath="Key" SelectedValuePath="Value"
            SelectionMode="Extended" Margin="0,10"/>
        <StackPanel Grid.Column="1" Grid.Row="0" VerticalAlignment="Center">
            <Button Content="Add" x:Name="Add_Button" Click="Add_Button_Click"/>
        </StackPanel>
        <StackPanel Grid.Column="1" Grid.Row="2" VerticalAlignment="Center">
            <Button Content="Remove" x:Name="Remove_Button" Click="Remove_Button_Click"/>
        </StackPanel>
        <ListBox x:Name="RightListBox" Grid.Row="0" Grid.RowSpan="3" Grid.Column="2"
            ItemsSource="{Binding RightListBoxItems}" DisplayMemberPath="Key" SelectedValuePath="Value"
            SelectionMode="Extended" Margin="0,10"/>

        <StackPanel Grid.Column="4" Grid.Row="1" Grid.RowSpan="1" Margin="0,10">
            <TextBox Text="{Binding SelectedValue.Step, ElementName=RightListBox}"/>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs

MainWindow.xaml.cs

using ListBoxMoveAll.Model;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;

namespace ListBoxMoveAll
{
    public partial class MainWindow : Window
    {
        public ObservableCollection<Dictionary<string, Graph>> LeftListBoxItems { get; } 
            = new ObservableCollection<Dictionary<string, Graph>>();
        public ObservableCollection<Dictionary<string, Graph>> RightListBoxItems { get; } 
            = new ObservableCollection<Dictionary<string, Graph>>();

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;

            Dictionary<string, Graph> Dic = new Dictionary<string, Graph>();
            Dic.Add("T1", new Graph(10));
            Dic.Add("T2", new Graph(20));
            Dic.Add("T3", new Graph(30));

            LeftListBoxItems.Add(Dic);

            // Yes! There are three items in Dic!
            foreach (var item in Dic)
            {
                MessageBox.Show(item.ToString());
            }
        }

        private void Add_Button_Click(object sender, RoutedEventArgs e)
        {
            //foreach (TestModel item in LeftListBox.SelectedItems.OfType<TestModel>().ToList())
            foreach (Dictionary<string, Graph> item 
                in LeftListBox.SelectedItems.OfType<Dictionary<string, Graph>>().ToList())
            {
                LeftListBoxItems.Remove(item);
                RightListBoxItems.Add(item);
            }
        }

        private void Remove_Button_Click(object sender, RoutedEventArgs e)
        {
            foreach (Dictionary<string, Graph> item 
                in RightListBox.SelectedItems.OfType<Dictionary<string, Graph>>().ToList())
            {
                RightListBoxItems.Remove(item);
                LeftListBoxItems.Add(item);
            }
        }
    }
}

Model/Graph.cs

Model/Graph.cs

namespace ListBoxMoveAll.Model
{
    public class Graph
    {
        public Graph(int step) { Step = step; }

        public int Step { get; set; }
    }
}

由于foreach语句显示Dic中包含三个项目,因此我认为我的XAML存在问题,但我无法弄清楚.你们可能知道问题所在.抱歉,这是一个非常基本的问题.谢谢您.

Since the foreach statement shows that there are three items in Dic, I think my XAML has an issue, but I cannot figure that out. You guys might know what the issue is. Sorry if this is a very basic question ... Thank you in advance.

新发现:我为LeftListBoxItems添加了另一个foreach语句:

New Discovery: I've added another foreach statement for LeftListBoxItems:

foreach (var item in LeftListBoxItems)
            {
                MessageBox.Show(item.ToString());
            }

...输出仅一次,内容为:

... The output is only once and the content is:

System.Collections.Generic.Dictionary`2[System.String,ListBoxMoveAll.Model.Graph]

这是什么意思?

推荐答案

由于使用的是数据绑定,因此正确"的处理方式是将文本和项目都包装在视图模型中:

Since you're using data binding the "proper" way to handle this is to wrap both the text and item in a view model:

public class GraphViewModel
{
    public string Text { get; }
    public Graph Graph { get; }

    public GraphViewModel(string text, Graph graph) => (Text, Graph) = (text, graph);
}

无需字典,您的收藏集可以改用以下类型:

No need for the dictionary, your collections can use this type instead:

    public ObservableCollection<GraphViewModel> LeftListBoxItems { get; } = new ObservableCollection<GraphViewModel>();
    public ObservableCollection<GraphViewModel> RightListBoxItems { get; } = new ObservableCollection<GraphViewModel>();

类似地,将项目添加到字典中只是为了随后将它们立即添加到集合中,没有任何意义,只需将它们直接添加到集合中即可:

Similarly, there's no point in adding items to a dictionary only to add them to the collection immediately afterwards, just add them to the collection directly:

LeftListBoxItems.Add(new GraphViewModel("T1", new Graph(10)));
LeftListBoxItems.Add(new GraphViewModel("T2", new Graph(20)));
LeftListBoxItems.Add(new GraphViewModel("T3", new Graph(30)));

对每个按钮处理程序进行了较小的更改:

A minor change to each of your button handlers:

foreach (var item in LeftListBox.SelectedItems.Cast<GraphViewModel>().ToList())
... and ...
foreach (var item in RightListBox.SelectedItems.Cast<GraphViewModel>().ToList())

最后,将列表框DisplayMemberPath属性绑定到Text并摆脱SelectedValuePath:

Finally, bind your list box DisplayMemberPath properties to Text and get rid of the SelectedValuePath:

<ListBox x:Name="LeftListBox" Grid.Row="0" Grid.RowSpan="3" Grid.Column="0"
    ItemsSource="{Binding LeftListBoxItems}" DisplayMemberPath="Text"
    SelectionMode="Extended" Margin="0,10"/>

<ListBox x:Name="RightListBox" Grid.Row="0" Grid.RowSpan="3" Grid.Column="2"
    ItemsSource="{Binding RightListBoxItems}" DisplayMemberPath="Text"
    SelectionMode="Extended" Margin="0,10"/>

这类似于Genos Loser的第二个示例,但是视图模型比KeyValuePair更具有类型安全性,并且如果需要的话,在以后添加INPC也会更容易.

This is similar to Genos Loser's 2nd example, but a view model is more typesafe than a KeyValuePair and it's also easier to add INPC to later if you need to.

这篇关于如何在列表框中显示多个词典项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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