如何将Combobox.Datasource转换为字典?

6

以下是我的代码,它将一个List()绑定到一个ComboBox控件。我试图使用Insert()方法向CombBox控件添加几个项目,但由于已将其分配给数据源,因此这是不允许的。那么,我该如何从返回对象的cmbColour.DataSource中获取数据源并将其存储到一个新变量(例如var colours2)中。谢谢!

var colours= new Dictionary<string, string>
            {
              {"1x","Green"},
              {"2x","Red"},
              {"3y","Blue"},
              {"4y","Black"}
            }.ToList();

cmbColour.ValueMember = "Key";
cmbColour.DisplayMember = "Value";
cmbColour.DataSource = colours;

var colours2 = //how can I get the DataSource back 
5个回答

7
下面的代码将返回一个新的字典,其中包含您绑定到组合框的相同数据。
var list = (List<KeyValuePair<String, String>>)cmbColor.DataSource;

var dictionary = list.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

属性DataSource将返回您分配的相同实例,但因为它是类型为Object,所以在访问任何成员之前必须将其强制转换回实际类型。
但为什么不保留原始字典呢?而且修改绑定到数据源的列表肯定是被支持的 - 这就是数据绑定的全部意义。
我想我的答案并没有真正解决你的实际问题,只是解决了你认为的问题。也许您可以提供一些额外的信息,说明您正在尝试实现什么,我或其他人将能够帮助您解决潜在的问题。
更新:
这应该适用于您的情况 - 我将使用用户示例。
public class User
{
    public String Id { get; set; }

    public String Name { get; set; }
}

以下是表单的代码。

public partial class MainForm : Form
{
    private readonly BindingList<User> recentlyAddedUsers = new BindingList<User>();

    private void MainFormLoad(Object sender, EventArgs e)
    {
        this.comboBoxRecentlyAddedUsers.DataSource = this.recentlyAddedUsers;

        this.comboBoxRecentlyAddedUsers.ValueMember = "Id";
        this.comboBoxRecentlyAddedUsers.DisplayMember = "Name";

        var recentlyAddedUsersFromService = this.GetRecentlyAddedUsers();

        foreach (var user in recentlyAddedUsersFromService)
        {
            this.recentlyAddedUsers.Add(user);
        }
    }

    private void ButtonAddNewUserClick(Object sender, EventArgs e)
    {
        var newUser = new User();

        newUser.Id = this.textBoxUserId.Text;
        newUser.Name = this.textBoxUserName.Text;

        this.SaveNewUser(newUser);

        this.recentlyAddedUsers.RemoveAt(0);
        this.recentlyAddedUsers.Insert(newUser);
    }

    private List<User> GetRecentlyAddedUsers()
    {
        // Get a list of recently added users from the database.
    }

    private void SaveNewUser(User user)
    {
        // Save the new user to the database.
    }
}

请注意使用 BindingList<T> - 这将通知组合框列表中的任何更改。简单的 List<T> 也可以工作,但是您必须显式告诉组合框刷新数据绑定。

+1 这个完美运作!!!实际上,我需要在列表中保留选定数量的项目,并将一个添加到顶部,从底部删除一个。初始列表来自 Web 服务。 - user1274686
好的,但是在将列表绑定到控件之前就可以完成所有操作。为什么你想要稍后恢复字典呢?获取SelectedValueSelectedIndex不就足够了吗? - Daniel Brückner
我现在想通了 - 看看我添加的示例,这个对你有用吗?这将是一种更清晰的解决方案。 - Daniel Brückner
非常感谢!我想多给你点赞,但我不能... 我喜欢使用BindingList<T>这个绝妙的想法!我会尝试并一定会告诉您结果。谢谢! - user1274686
我已经采纳了你的绝妙想法。这样更加整洁!有点新鲜。再次感谢!五星好评!!! - user1274686
显示剩余3条评论

1

由于DataSource被定义为一个object,因此没有一种简单的方法来从中提取数据。如果您知道数据源的基础类型(也就是说,在其他地方设置了它,所以您知道它的类型),您可以将其强制转换并将项目添加到集合中。

请注意,该对象将是原始对象的引用而不是副本,这意味着如果您最初将数据源设置为字典,然后尝试将其提取以添加项目,则会向相同的字典添加项目。

所以在您的情况下:

 var colours2 = cmbColour.DataSource as List<KeyValuePair<string, string>>;
 // can add items to colours2 here (but it is the same instance as colours)

请注意,在将字典分配给数据源之前,op 在字典上调用了 ToList() 方法,因此尝试将其转换为字典会返回 null。 - Will

1
var coloursList = cmbColour.DataSource as List<KeyValuePair<string, string>>;
var colours2 = coloursList.ToDictionary(x => x.Key, x => x.Value);

2
如果您知道要转换的值始终是您要转换到的类型,则不要使用 as。如果您期望 x 始终为字符串类型,请使用 (String)x,因为如果出现错误并且 x 不是字符串类型,它将抛出异常。使用 x as String 将导致错误未被发现,看起来就像 xnull - Daniel Brückner

0

您可以使用以下转换方式获取数据。

namespace WebApplication2
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var colours = new Dictionary<string, string>
            {
                {"1x", "Green"},
                {"2x", "Red"},
                {"3y", "Blue"},
                {"4y", "Black"}
            }.ToList();

            cmbColour.DataSource = colours;

            List<KeyValuePair<string, string>> l1 = new List<KeyValuePair<string, string>>();

            l1 = (List<KeyValuePair<string, string>>)cmbColour.DataSource;
        }
    }
}

你正在创建一个新列表并将其分配给l1,只是为了在下一条语句中将其丢弃。细节不大——问题是关于WinForms而不是WebForms,但这并不重要。 - Daniel Brückner

0
List<KeyValuePair<String, String>> c = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("m", "n"),
            new KeyValuePair<string, string>("k", "c")
        };

comboBox1.DataSource = c;

c.Add(new KeyValuePair<string, string>("new","new value"));

或者

var list = (List<KeyValuePair<String, String>>)comboBox1.DataSource;
list.Add(new KeyValuePair<string, string>("new", "new value"));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接