带枚举的 DataGridView 仅在 BindingList 中设置默认值

本文关键字:设置 默认值 BindingList 仅在 枚举 DataGridView | 更新日期: 2023-09-27 18:32:32

>背景:我正在创建一个简单的winform 应用程序供个人使用,以查询我通过XML序列化记录的数据。 这些数据包括英雄及其相关的种族、职业等。 我的问题发生在旨在添加新冠军的用户控件中。

问题:我正在使用 DataGridViews 向新英雄添加 1 个或多个种族、职业等。 其中每个属性都是枚举类型。 每个 DataGridView 都绑定到一个枚举类型,具有一列组合框来选择所需的值。

种族数据网格视图示例:(抱歉,我有屏幕截图,但没有足够的代表。

[__|_ChampRace________________]

[_ .... _|_Dragon__________________v_]

[__* __|____

这些 DataGridView 的源都绑定到每个枚举类型的 BindingLists。当我在视图中选择一个值(比如ChampRace.Dragon(时,BindingList只接收默认的附加值(ChampRace.None(。为什么绑定列表没有按照我的意愿更新?

示例枚举:

public enum ChampRace
{
    None,
    Angel,
    Beast,
    Dragon,
    Etc
}

序列化类:

public class Champion
{
    [XmlAttribute]
    public string Name { get; set; }
    [XmlElement]
    public List<ChampRace> Races { get; set; }
    [XmlElement]
    public List<ChampClass> Classes { get; set; }
    [XmlElement]
    public List<Faction> Factions { get; set; }
}

用户控件代码隐藏:

public partial class NewChampion : UserControl
{
    public NewChampion()
    {
        this.InitializeComponent();
        this.InitializeAllData();
    }
    public Master Master { get; set; }
    public BindingList<ChampRace> Races { get; set; }
    public BindingList<ChampClass> Classes { get; set; }
    public BindingList<Faction> Factions { get; set; }
    private void AddChampionButton_Click(object sender, EventArgs e)
    {
        Champion champion = new Champion();
        champion.Name = this.nameTextBox.Text;
        champion.Classes = new List<ChampClass>();
        champion.Factions = new List<Faction>();
        champion.Races = new List<ChampRace>();
        foreach (ChampClass cc in this.Classes)
        {
            champion.Classes.Add(cc);
        }
        foreach (ChampRace cr in this.Races)
        {
            champion.Races.Add(cr);
        }
        foreach (Faction f in this.Factions)
        {
            champion.Factions.Add(f);
        }
        System.Diagnostics.Debug.WriteLine("Break point here during debug to verify data...");
        // Note: At this point based on the screenshot, this.Races has one value.
        // Instead of the expected value "Dragon", the value is always "None".
    }
    private void InitializeAllData()
    {
        this.Races = new BindingList<ChampRace>();
        this.Classes = new BindingList<ChampClass>();
        this.Factions = new BindingList<Faction>();
        /*
         *  The following event handlers were added to show a new editable row in the dgView.
         *  Without them, no rows appear.
         */
        this.Classes.AddingNew += (s, e) =>
        {
            // e.NewObject = ChampClass.None;
        };
        this.Races.AddingNew += (s, e) =>
        {
            // e.NewObject = ChampRace.None;
        };
        this.Factions.AddingNew += (s, e) =>
        {
            // e.NewObject = Faction.None;
        };
        this.raceData.DataSource = this.Races;
        this.classData.DataSource = this.Classes;
        this.factionData.DataSource = this.Factions;
        this.SetupDataOptions<ChampRace>(ref this.raceData);
        this.SetupDataOptions<ChampClass>(ref this.classData);
        this.SetupDataOptions<Faction>(ref this.factionData);
    }
    private void SetupDataOptions<T>(ref DataGridView data)
        where T : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("Type must be an enumeration");
        }
        DataGridViewComboBoxColumn combo = new DataGridViewComboBoxColumn();
        combo.ValueType = typeof(T);
        combo.DataSource = Enum.GetValues(typeof(T));
        combo.DataPropertyName = typeof(T).ToString();
        combo.Name = typeof(T).ToString().Split('.').Last();
        data.AutoGenerateColumns = false;
        data.AutoSize = true;
        data.Columns.Add(combo);
    }
}

这是我第一次使用 DataGridViews 和 BindingLists,所以我希望这是一个容易被忽视的错误。

我发现的最相关的研究让我来到这里:

  1. 如果值是枚举,则组合框不会设置默认值
  2. 使 DataGridView 列在绑定到绑定列表后可编辑
  3. DataGridView 不更新 BindingList 中的枚举
  4. 组合框列上的数据网格视图默认错误

带枚举的 DataGridView 仅在 BindingList 中设置默认值

我在测试程序中重新创建了代码,发现 BindingList 的行为与您所说的一样。 它保留枚举对象的列表,但将其保留在第一个枚举处。 由于绑定列表至少有一个枚举对象,因此我能够使用 DataGridView 事件来完成数据更新。 在 DataGridView 中,有一个事件 CellValueChanged。 我按如下方式实现了该事件:

private void DataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
      this.bindingList[e.RowIndex] = (myEnumeration)DataGridView[e.ColumnIndex, e.RowIndex].Value;
}

这会将值放在 BindingList 中,只需多写几行代码。