在DataGridView中编辑并存储在app.settings中 [英] Edit in DataGridView and store in app.settings
问题描述
嗨伙计们,
生效了,我需要一个用户可以编辑的字典,并存储在app.config中。
app.config似乎不喜欢泛型。至少我无法创建一个泛型作为其类型的设置。甚至不是通过键入完全限定的名称而不是搜索可用的类型。
所以我创建了一个实现IXmlSerializable的非泛型类(修改后的这个)来存储数据。
对于用户更改设置,我只想抛出Properties.Settings。在PropertyGrid中默认并让它处理所有编辑。因此,我的类设置了TypeConverter和Editor属性,以便最终将该类的实例分配给DataGridView.DataSource。由于设置了BindingList<>正如DataSource一样,我也在我的类上实现了IBindingList,但是DataGridView仍然是空的。
我可以在调试器中看到实例包含数据,但是DataGridView只是没有除了它的DarkGrey背景之外什么都没有显示。
什么类似乎能够作为DataGridView的DataSource工作?
我的课程已附上。它可能看起来像代码转储,但我无法弄清楚哪个部分可能是错误的(或缺失的)。
Hi folks,
in effect, I need to have a dictionary that user can edit and that's stored in app.config.
app.config doesn't like generics, it seems. At least I couldn't create a setting with a generic as its type. Not even by typing the fully qualified name instead of searching through the available types.
So I created a non-generic class that implements IXmlSerializable (modified this) to store the data.
For the user to change settings, I just wanted to throw Properties.Settings.Default at a PropertyGrid and let it handle all the editing. My class therefore has TypeConverter and Editor attributes set so that an instance of that class finally is assigned to a DataGridView.DataSource. Since setting a BindingList<> as DataSource works, I also implemented IBindingList on my class, but the DataGridView stays empty.
I can see in the debugger that the instance contains data, but DataGridView just doesn't show anything except its DarkGrey background.
What is a class supposed to look like to be able to work as DataGridView's DataSource?
My class is attached. It may seem like a code dump, but I just can't figure out what part may be the wrong (or missing) one.
[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
}
推荐答案
Hello,
How about simple solution to store key/value as string collection? App settings gives possibility to store array of string in collection of type:
Hello,
How about simple solution to store key/value as string collection? App settings gives possibility to store array of string in collection of type:
System.Collections.Specialized.StringCollection
As I see you need to store dictionary of <ulong,ulong> so, why not to create own simple custom class like this:
As I see you need to store dictionary of <ulong,ulong> so, why not to create own simple custom class like this:
public class KeyValueClass
{
public ulong Key { get; set; }
public ulong Value { get; set; }
}
Then store values in string array in this format:
Key,Value
123541098054,498902112342
423442223,2344842904
Then store values in string array in this format:
Key,Value
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>
Remember to check values are correct while reading from app settings and don’t forget to implement INotifyPropertyChanged in KeyValueClass.
I hope it help you.
Remember to check values are correct while reading from app settings and don't forget to implement INotifyPropertyChanged in KeyValueClass.
I hope it help you.
这篇关于在DataGridView中编辑并存储在app.settings中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!