Редактирование в 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 }