Created
April 5, 2019 09:07
-
-
Save weltkante/e4a616d629e09cf88b25aaf7864080c2 to your computer and use it in GitHub Desktop.
2d array wrapper for WPF datagrid binding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public sealed class ArrayBinder : IBindingList, ITypedList | |
{ | |
private sealed class ArrayColumn : PropertyDescriptor | |
{ | |
public ArrayBinder Owner { get; } | |
public int ColumnIndex { get; } | |
public ArrayColumn(ArrayBinder owner, int index) | |
: base($"[{index}]", null) | |
{ | |
Owner = owner; | |
ColumnIndex = index; | |
} | |
public override bool IsReadOnly => !Owner.AllowEdit; | |
public override Type ComponentType => typeof(ArrayRow); | |
public override Type PropertyType => typeof(object); | |
public override object GetValue(object component) | |
{ | |
var row = component as ArrayRow; | |
if (row == null || row.Owner != Owner) | |
throw new ArgumentException(); | |
return Owner._array[row.RowIndex, ColumnIndex]; | |
} | |
public override void SetValue(object component, object value) | |
{ | |
if (IsReadOnly) | |
throw new InvalidOperationException(); | |
var row = component as ArrayRow; | |
if (row == null || row.Owner != Owner) | |
throw new ArgumentException(); | |
Owner._array[row.RowIndex, ColumnIndex] = value; | |
} | |
public override bool ShouldSerializeValue(object component) | |
{ | |
return false; | |
} | |
public override bool CanResetValue(object component) | |
{ | |
return false; | |
} | |
public override void ResetValue(object component) | |
{ | |
throw new NotSupportedException(); | |
} | |
} | |
private sealed class ArrayRow | |
{ | |
public ArrayBinder Owner { get; } | |
public int RowIndex { get; } | |
public ArrayRow(ArrayBinder owner, int index) | |
{ | |
Owner = owner; | |
RowIndex = index; | |
} | |
// Workaround: WPF does not honor the PropertyDescriptor GetValue/SetValue implementation, but instead binds directly against the indexer | |
public object this[int ColumnIndex] | |
{ | |
get => Owner._array[RowIndex, ColumnIndex]; | |
set | |
{ | |
if (!Owner.AllowEdit) | |
throw new InvalidOperationException(); | |
Owner._array[RowIndex, ColumnIndex] = value; | |
} | |
} | |
} | |
private object[,] _array; | |
private ArrayRow[] _rows; | |
private PropertyDescriptorCollection _columns; | |
public ArrayBinder(object[,] source, bool allowEdit) | |
{ | |
this.AllowEdit = allowEdit; | |
_array = source; | |
_rows = new ArrayRow[source.GetLength(0)]; | |
for (int i = 0; i < _rows.Length; i++) | |
_rows[i] = new ArrayRow(this, i); | |
var columns = new ArrayColumn[source.GetLength(1)]; | |
for (int i = 0; i < columns.Length; i++) | |
columns[i] = new ArrayColumn(this, i); | |
_columns = new PropertyDescriptorCollection(columns, true); | |
} | |
public object this[int index] | |
{ | |
get => _rows[index]; | |
set => throw new NotSupportedException(); | |
} | |
public bool AllowNew => false; // adding rows is not possible on a 2d array | |
public bool AllowEdit { get; set; } | |
public bool AllowRemove => false; // removing rows is not possible on a 2d array | |
public bool SupportsChangeNotification => false; | |
public bool SupportsSearching => false; | |
public bool SupportsSorting => false; | |
public bool IsSorted => false; | |
public PropertyDescriptor SortProperty => null; | |
public ListSortDirection SortDirection => ListSortDirection.Ascending; | |
public bool IsReadOnly => true; // we allow editing row values (AllowEdit) not editing the list itself | |
public bool IsFixedSize => true; // adding/removing rows is not possible on a 2d array | |
public int Count => _rows.Length; | |
public object SyncRoot => this; | |
public bool IsSynchronized => false; | |
public event ListChangedEventHandler ListChanged { add { } remove { } } | |
public int Add(object value) => throw new NotSupportedException(); | |
public void AddIndex(PropertyDescriptor property) { } | |
public object AddNew() => throw new NotSupportedException(); | |
public void ApplySort(PropertyDescriptor property, ListSortDirection direction) => throw new NotSupportedException(); // SupportsSorting is false | |
public void Clear() => throw new NotSupportedException(); | |
public bool Contains(object value) => IndexOf(value) >= 0; | |
public void CopyTo(Array array, int index) => _rows.CopyTo(array, index); | |
public int Find(PropertyDescriptor property, object key) => throw new NotSupportedException(); // SupportsSorting is false | |
public IEnumerator GetEnumerator() => _rows.GetEnumerator(); | |
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors) | |
{ | |
if (listAccessors != null && listAccessors.Length != 0) | |
throw new NotSupportedException(); | |
return _columns; | |
} | |
public string GetListName(PropertyDescriptor[] listAccessors) => null; | |
public int IndexOf(object value) | |
{ | |
var row = value as ArrayRow; | |
if (row != null && row.Owner == this) | |
return row.RowIndex; | |
return -1; | |
} | |
public void Insert(int index, object value) => throw new NotSupportedException(); | |
public void Remove(object value) => throw new NotSupportedException(); | |
public void RemoveAt(int index) => throw new NotSupportedException(); | |
public void RemoveIndex(PropertyDescriptor property) { } | |
public void RemoveSort() { } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment