DataGridView с перечислениями только устанавливает значение по умолчанию в BindingList

Справочная информация: я создаю простое приложение winform для личного использования для запроса данных, которые я зарегистрировал с помощью XML-сериализации. Эти данные состоят из чемпионов и связанных с ними рас (классов), классов (классов) и т. Д. Моя проблема возникает в пользовательском контроле, предназначенном для добавления новых чемпионов.

Проблема: я использую DataGridViews, чтобы добавить 1 или более Race, Class и т. Д. К новому чемпиону. Каждое из этих свойств является типом enum. Каждый DataGridView привязан к одному типу перечисления, имеющему один столбец со списками для выбора желаемых значений.

Пример DataGridView for Race: (Извините, у меня был скриншот, но мне не хватает представителя.)

[_____ | _ChampRace ________________]

[_.... _ | _Dragon __________________ v_]

[__ * __ | ________________________ v _]

Источник этих DataGridView каждый связан с BindingLists каждого типа перечисления. Когда я выбираю значение в представлении (скажем, ChampRace.Dragon), BindingList получает только добавленное значение по умолчанию (ChampRace.None). Почему список привязок не обновляется по моему желанию?

Пример Enums:

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; }
}

Код UserControl позади:

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. Combobox не устанавливает значение по умолчанию, если значение является перечислением
  2. Создание редактируемого столбца DataGridView после привязки его к BindingList
  3. DataGridView не обновляет Enum в BindingList
  4. Ошибка DataGridView по умолчанию для столбца ComboBox

1 ответ

Решение

Я воссоздал код в тестовой программе и обнаружил, что BindingList ведет себя так, как вы утверждаете. Он хранит список объектов перечисления, но оставляет его при первом перечислении. Так как список привязок, по крайней мере, имеет объект перечисления, я смог использовать событие DataGridView для выполнения обновления данных. В DataGridView есть событие CellValueChanged. Я реализовал событие следующим образом:

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

Это помещает значение в BindingList с помощью нескольких дополнительных строк кода.

Другие вопросы по тегам