lukeer Ответов: 2

Редактирование в datagridview и сохранить в приложение.параметры


Привет ребята,

по сути, мне нужен словарь, который пользователь может редактировать и который хранится в файле app.config.

похоже, app.config не любит дженерики. По крайней мере, я не мог создать настройку с общим типом в качестве ее типа. Даже не вводя полное имя вместо поиска по доступным типам.
Поэтому я создал не универсальный класс, который реализует IXmlSerializable (модифицированный этот) для хранения данных.

Для пользователя, чтобы изменить настройки, я просто хотел бросить свойства.Настройки.По умолчанию используется PropertyGrid, и пусть он обрабатывает все редактирование. Поэтому мой класс имеет атрибуты TypeConverter и Editor, установленные таким образом, что экземпляр этого класса в конечном итоге назначается DataGridView.DataSource. Поскольку установка BindingList<> В качестве источника данных работает, я также реализовал IBindingList в своем классе, но DataGridView остается пустым.

Я вижу в отладчике, что экземпляр содержит данные, но DataGridView просто не показывает ничего, кроме своего темно-серого фона.

Как должен выглядеть класс, чтобы он мог работать в качестве источника данных DataGridView?

Мой класс прикреплен. Это может показаться свалкой кода, но я просто не могу понять, какая часть может быть неправильной (или отсутствующей).

[System.ComponentModel.TypeConverter(typeof(DictionaryConverter))]
[System.ComponentModel.Editor(typeof(Pulsotronic.Model.DictionaryEditor), typeof(System.Drawing.Design.UITypeEditor))]
[XmlRoot("dictionary")]
public class SerializableDictionary : System.ComponentModel.IBindingList, IXmlSerializable
{
    #region Declarations

    private class LutEntry : System.ComponentModel.INotifyPropertyChanged
    {
        #region Declarations

        public ulong Key { get; private set; }
        private int _hashCode;
        private ulong _value;

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        #endregion


        #region Init

        public LutEntry(ulong key, ulong value)
        {
            this.Key = key;
            this.Value = value;

            this._hashCode = (int)(key % int.MaxValue);
        }

        #endregion


        #region Information Disclosure

        public ulong Value
        {
            get { return (_value); }
            set
            {
                _value = value;
                System.ComponentModel.PropertyChangedEventHandler eh = PropertyChanged;
                if (eh != null)
                {
                    eh(this, new System.ComponentModel.PropertyChangedEventArgs("Value"));
                }
            }
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj))
            {
                return (true);
            }

            LutEntry input = obj as LutEntry;
            if (obj == null)
            {
                return (false);
            }

            return (this.Key.Equals(input.Key));
        }

        // Todo: resolve Stack Overflow
        public static bool operator ==(LutEntry first, LutEntry second)
        {
            if (object.ReferenceEquals(first, second))
            {
                return (true);
            }

            if (
                (object)first == null
                || (object)second == null
            )
            {
                return (false);
            }

            return (first.Key == second.Key);
        }

        public static bool operator !=(LutEntry first, LutEntry second)
        {
            return (!(first == second));
        }

        public override int GetHashCode()
        {
            return (_hashCode);
        }

        #endregion
    }

    private System.ComponentModel.BindingList<LutEntry> _innerList = new System.ComponentModel.BindingList<LutEntry>();

    public event System.ComponentModel.ListChangedEventHandler ListChanged;

    #endregion


    #region Init

    public SerializableDictionary()
    {
        this.Add(123456789, 10001000);
        this.Add(123456798, 10011000);
        this.Add(123456879, 10021001);
        this.Add(123456897, 10031002);
    }

    #endregion


    #region Grow And Shrink

    private int Add(LutEntry value)
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }

        if (this.ContainsKey(value.Key))
        {
            throw new ArgumentException("Entry \"" + value.Key.ToString() + "\" is already present.");
        }

        _innerList.Add(value);
        int index = _innerList.Count - 1;

        System.ComponentModel.ListChangedEventHandler eh = ListChanged;
        if (eh != null)
        {
            eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, index));
        }

        return (index);
    }


    public int Add(object value)
    {
        LutEntry input = value as LutEntry;
        if (input == null)
        {
            throw new ArgumentException("\"" + value.ToString() + "\" is not of type \"LutEntry\"");
        }

        return (this.Add(input));
    }


    public int Add(ulong key, ulong value)
    {
        return (this.Add(new LutEntry(key, value)));
    }


    public object AddNew()
    {
        LutEntry newOne = _innerList.AddNew();

        System.ComponentModel.ListChangedEventHandler eh = ListChanged;
        if (eh != null)
        {
            eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, 0));
        }

        return (newOne);
    }

    public void Insert(int index, object value)
    {
        _innerList.Insert(index, (LutEntry)value);

        System.ComponentModel.ListChangedEventHandler eh = ListChanged;
        if (eh != null)
        {
            eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.ItemAdded, index));
        }
    }

    public void Remove(object value)
    {
        // Could have been passed a LutEntry object
        LutEntry input = value as LutEntry;

        // Or an ulong as well, in which case try
        //   to find the corresponding LutEntry.
        if (value is ulong)
        {
            foreach (LutEntry entry in _innerList)
            {
                if (entry.Key == (ulong)value)
                {
                    input = entry;
                    break;
                }
            }
        }

        // Delete the LutEntry in question.
        if (input != null)
        {
            _innerList.Remove(input);
        }

        System.ComponentModel.ListChangedEventHandler eh = ListChanged;
        if (eh != null)
        {
            eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, 0));
        }
    }

    public void RemoveAt(int index)
    {
        _innerList.RemoveAt(index);

        System.ComponentModel.ListChangedEventHandler eh = ListChanged;
        if (eh != null)
        {
            eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.ItemDeleted, index));
        }
    }

    public void Clear()
    {
        _innerList.Clear();

        System.ComponentModel.ListChangedEventHandler eh = ListChanged;
        if (eh != null)
        {
            eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, 0));
        }
    }

    #endregion


    #region Sort

    public void ApplySort(System.ComponentModel.PropertyDescriptor property, System.ComponentModel.ListSortDirection direction)
    {
        ((System.ComponentModel.IBindingList)_innerList).ApplySort(property, direction);

        System.ComponentModel.ListChangedEventHandler eh = ListChanged;
        if (eh != null)
        {
            eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, 0));
        }
    }

    public void RemoveSort()
    {
        ((System.ComponentModel.IBindingList)_innerList).RemoveSort();

        System.ComponentModel.ListChangedEventHandler eh = ListChanged;
        if (eh != null)
        {
            eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, 0));
        }
    }

    public void AddIndex(System.ComponentModel.PropertyDescriptor property)
    // http://msdn.microsoft.com/en-us/library/system.componentmodel.ibindinglist.addindex.aspx
    // "The list must support this method. However, support for this method can be a nonoperation."
    {
        ((System.ComponentModel.IBindingList)_innerList).AddIndex(property);
    }

    public void RemoveIndex(System.ComponentModel.PropertyDescriptor property)
    // http://msdn.microsoft.com/en-us/library/system.componentmodel.ibindinglist.removeindex.aspx
    // "The list must support this method. However, support for this method can be a nonoperation."
    {
        ((System.ComponentModel.IBindingList)_innerList).RemoveIndex(property);
    }

    public bool IsSorted
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).IsSorted); }
    }

    public System.ComponentModel.ListSortDirection SortDirection
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).SortDirection); }
    }

    public System.ComponentModel.PropertyDescriptor SortProperty
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).SortProperty); }
    }

    public bool SupportsSorting
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).SupportsSorting); }
    }

    #endregion


    #region Value Handling

    public ulong this[ulong key]
    {
        get
        {
            foreach (LutEntry entry in _innerList)
            {
                if (key == entry.Key)
                {
                    return (entry.Value);
                }
            }

            throw new ArgumentOutOfRangeException("Entry with key \"" + key.ToString() + "\" not found in list");
        }
    }


    public object this[int index]
    {
        get
        {
            return (_innerList[index]);
        }
        set
        {
            LutEntry newEntry = value as LutEntry;
            if (newEntry == null)
            {
                throw new ArgumentException("\"" + value.ToString() + "\" is null or not of type \"LutEntry\".");
            }
            if (this.ContainsKey(newEntry.Key))
            {
                throw new ArgumentException("Entry with key \"" + newEntry.Key + "\" already found in list");
            }

            _innerList[index] = newEntry;

            System.ComponentModel.ListChangedEventHandler eh = ListChanged;
            if (eh != null)
            {
                eh(this, new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.ItemChanged, index));
            }
        }
    }


    public bool Contains(object value)
    {
        LutEntry input = value as LutEntry;
        if (input != null)
        {
            return (_innerList.Contains(input));
        }

        if (value is ulong)
        {
            foreach (LutEntry match in _innerList)
            {
                if (match.Key == (ulong)value)
                {
                    return (true);
                }
            }
        }

        return (false);
    }


    public bool ContainsKey(ulong key)
    {
        foreach (LutEntry entry in _innerList)
        {
            if (key == entry.Key)
            {
                return (true);
            }
        }

        return (false);
    }


    public int IndexOf(object value)
    {
        LutEntry input = value as LutEntry;
        if (input != null)
        {
            return (_innerList.IndexOf(input));
        }

        if (value is ulong)
        {
            for (int i = 0; i < _innerList.Count; i++)
            {
                if (_innerList[i].Key == (ulong)value)
                {
                    return (i);
                }
            }
        }

        return (-1);
    }

    #endregion


    #region XMLSerialize

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(ulong));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(ulong));

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if (wasEmpty)
            return;

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");

            reader.ReadStartElement("key");
            ulong key = (ulong)keySerializer.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement("value");
            ulong value = (ulong)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement();
            reader.MoveToContent();
        }
        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(ulong));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(ulong));

        foreach (LutEntry match in this._innerList)
        {
            writer.WriteStartElement("item");

            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, match.Key);
            writer.WriteEndElement();

            writer.WriteStartElement("value");
            //ulong value = this[key];
            valueSerializer.Serialize(writer, match.Value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }

    public System.Xml.Schema.XmlSchema GetSchema()
    // http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.getschema.aspx
    // "This method is reserved and should not be used. When implementing the IXmlSerializable interface,
    //  you should return null (Nothing in Visual Basic) from this method, and instead, if specifying
    //  a custom schema is required, apply the XmlSchemaProviderAttribute to the class"
    {
        return null;
    }

    #endregion


    #region Information Disclosure

    public bool AllowEdit
    {
        get { return (_innerList.AllowEdit); }
    }

    public bool AllowNew
    {
        get { return (_innerList.AllowNew); }
    }

    public bool AllowRemove
    {
        get { return (_innerList.AllowRemove); }
    }

    public void CopyTo(Array array, int index)
    {
        _innerList.CopyTo((LutEntry[])array, index);
    }

    public int Count
    {
        get { return (_innerList.Count); }
    }

    public int Find(System.ComponentModel.PropertyDescriptor property, object key)
    {
        return (((System.ComponentModel.IBindingList)_innerList).Find(property, key));
    }

    public System.Collections.IEnumerator GetEnumerator()
    {
        return (_innerList.GetEnumerator());
    }

    public bool IsFixedSize
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).IsFixedSize); }
    }

    public bool IsReadOnly
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).IsReadOnly); }
    }

    public bool IsSynchronized
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).IsSynchronized); }
    }

    public bool SupportsChangeNotification
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).SupportsChangeNotification); }
    }

    public bool SupportsSearching
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).SupportsSearching); }
    }

    public object SyncRoot
    {
        get { return (((System.ComponentModel.IBindingList)_innerList).SyncRoot); }
    }


    public override string ToString()
    {
        if (_innerList.Count <= 0)
        {
            return ("[Empty]");
        }

        StringBuilder outputBuilder = new StringBuilder();
        foreach (LutEntry match in _innerList)
        {
            outputBuilder.AppendFormat("{0}{1}{2}->{3}", Environment.NewLine, match.Key.ToString(), "\t", match.Value.ToString());
        }
        outputBuilder.Remove(0, 1);

        return (outputBuilder.ToString());
    }

    #endregion
}

2 Ответов

Рейтинг:
0

Marcin Kozub

Привет,

Как насчет простого решения для хранения ключа/значения в виде коллекции строк? Настройки приложения дают возможность хранить массив строк в коллекции типа:

System.Collections.Specialized.StringCollection


Как я вижу,вам нужно хранить словарь <ulong, ulong> Так почему бы не создать собственный простой пользовательский класс, подобный этому:

public class KeyValueClass
{
    public ulong Key { get; set; }
    public ulong Value { get; set; }
}


Затем сохраните значения в строковом массиве в этом формате:

ключевая ценность
123541098054,498902112342
423442223,2344842904

public partial class Form1 : Form
{
    private List<keyvalueclass> _values;
    private BindingSource _bindingSource;

    public Form1()
    {
        InitializeComponent();
        _bindingSource = new BindingSource();
    }

    private void btnLoad_Click(object sender, EventArgs e)
    {
        _values = new List<keyvalueclass>();
        if (Properties.Settings.Default.Values != null)
        {
            foreach (var stringValue in Properties.Settings.Default.Values)
            {
                var stringItems = stringValue.Split(",".ToCharArray());
                var item = new KeyValueClass();
                item.Key = ulong.Parse(stringItems[0]);
                item.Value = ulong.Parse(stringItems[1]);
                _values.Add(item);
            }
        }

        _bindingSource.DataSource = _values;
        dataGridView1.DataSource = _bindingSource;
    }

    private void btnSave_Click(object sender, EventArgs e)
    {
        Properties.Settings.Default.Values = new System.Collections.Specialized.StringCollection();
        foreach (var item in _values)
        {
            Properties.Settings.Default.Values.Add(string.Join(",", item.Key, item.Value));
        }
        Properties.Settings.Default.Save();
    }
}</keyvalueclass></keyvalueclass>


Не забудьте проверить правильность значений при чтении из настроек приложения и не забудьте реализовать INotifyPropertyChanged в KeyValueClass.

Надеюсь, это вам поможет.


Рейтинг:
0

communicore

миллион лет спустя... Я-это ... vb.net разработчик, так что если Ctype/Trycast имеют разные реализации в C#, просто игнорируйте меня!Интересно, если это как-то связано с использованием "как" кастинг (trycast в VB), который, очевидно, возвращает NULL, и лучший способ производства как у вас с этим, но для отладки (или будущий читатель) может хотите попробовать прямого литья (ctype или directcase в VB) просто для выявления возможных ошибок.