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

C# 带有枚举的DataGridView仅在BindingList中设置默认值,c#,winforms,datagridview,enums,bindinglist,C#,Winforms,Datagridview,Enums,Bindinglist,背景:我正在创建一个简单的winform应用程序,供个人使用,用于查询通过XML序列化记录的数据。这些数据包括冠军及其相关的种族(es)、职业(es)等。我的问题发生在一个旨在添加新冠军的用户控件中 问题:我正在使用DataGridView向新冠军添加一个或多个种族、职业等。每个属性都是枚举类型。每个DataGridView绑定到一个枚举类型,有一列组合框来选择所需的值 Race的DataGridView示例: (对不起,我有截图,但没有足够的代表。) [冠军赛,冠军赛] […..124;龙uu

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

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

Race的DataGridView示例: (对不起,我有截图,但没有足够的代表。)

[冠军赛,冠军赛]

[…..124;龙uuuuuuuuuuuuuuuuuuuuuuuuuv_uuuu]

[\uuu*\ uu124; uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuv]

这些DataGridView的源都绑定到每种枚举类型的绑定列表。当我在视图中选择一个值(比如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; }
}
公开课冠军
{
[XmlAttribute]
公共字符串名称{get;set;}
[XmlElement]
公共列表竞赛{get;set;}
[XmlElement]
公共列表类{get;set;}
[XmlElement]
公共列表派系{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);
    }
}
公共部分类NewChampion:UserControl
{
公众新冠军()
{
this.InitializeComponent();
这是.InitializeAllData();
}
公共主控主机{get;set;}
公共绑定列表{get;set;}
公共绑定列表类{get;set;}
公共绑定列表派系{get;set;}
私有void AddChampionButton_单击(对象发送者,事件参数e)
{
冠军=新冠军();
champion.Name=this.nameTextBox.Text;
champion.Classes=新列表();
champion.派系=新列表();
champion.Races=新列表();
foreach(本.Classes中的ChampClass cc)
{
champion.Classes.Add(cc);
}
foreach(本次比赛中的ChampRace cr)
{
冠军。比赛。添加(cr);
}
foreach(本章中的f派系。派系)
{
冠军。派系。添加(f);
}
System.Diagnostics.Debug.WriteLine(“调试过程中的断点用于验证数据…”);
//注意:根据屏幕截图,这个.Races有一个值。
//与预期值“Dragon”不同,该值始终为“None”。
}
private void InitializeAllData()
{
this.Races=newbindingslist();
this.Classes=newbindingList();
this.派系=新绑定列表();
/*
*添加了以下事件处理程序以在dgView中显示新的可编辑行。
*没有它们,就不会出现行。
*/
this.Classes.AddingNew+=(s,e)=>
{
//e.NewObject=ChampClass.None;
};
this.Races.AddingNew+=(s,e)=>
{
//e.NewObject=ChampRace.None;
};
this.particles.AddingNew+=(s,e)=>
{
//e.NewObject=派系。无;
};
this.raceData.DataSource=this.Races;
this.classData.DataSource=this.Classes;
this.派系数据源=this.派系;
此.SetupDataOptions(参考此.raceData);
this.SetupDataOptions(参考this.classData);
this.SetupDataOptions(参考此.SetupDataOptions);
}
私有void SetupDataOptions(参考DataGridView数据)
其中T:struct,i可比较,i可附加,i可转换
{
if(!typeof(T).IsEnum)
{
抛出新ArgumentException(“类型必须是枚举”);
}
DataGridViewComboBoxColumn组合=新建DataGridViewComboxColumn();
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(组合);
}
}
这是我第一次使用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中,只需要额外的几行代码