Assembly: Dapfor.Wpf (in Dapfor.Wpf.dll) Version: 4.1.0.26317 (4.1.0.26317)
Syntax
C# |
---|
public interface IDataField |
Visual Basic |
---|
Public Interface IDataField |
Visual C++ |
---|
public interface class IDataField |
F# |
---|
type IDataField = interface end |
Remarks
Wpf GridControl is able to manipulate various data types, including user defined classes, string arrays or other objects, IList<(Of <(<'T>)>)>, IDictionary<(Of <(<'TKey, TValue>)>)>, where TKey is a string identifier or some other type. As you remember, all this broad range of data can be inserted into the Wpf GridControl through the GridControl.Rows.Add(object) / Row.Add(object). Besides that, the grid can be connected to a data source that implements IList, IListSource or IBindingList interfaces.
Such broad functionality of the Wpf GridControl is possible due to the IDataAccessor interface that is one of the most crucial part of the grid. The main purpose of this interface is to normalize presentation of different data types in the grid. There are lots of implementations of IDataAccessor interface. This way, a programmer can add his own implementation to broaden the list of data types that can be used by the Wpf GridControl. When you call Add(Object), an implementation of the IDataAccessor interface is created implicitly for 'your object' and the Wpf GridControl works with it only via the IDataAccessor proxy, making no difference between the data types.
Intrinsically, IDataAccessor interface is nothing more than a simple 'container' for data object fields (IDataField object), that should be displayed in a grid cell. Each field contains an identifier, a name, a description, information about formats and editors, and it can be used to get values from a data object or to set values. Please note, that for different objects the process of getting or setting values of a data object may vary. For user-defined classes you can use the reflection mechanism to get or set values. For IList<(Of <(<'T>)>)> the grid gets them with a certain index; for IDictionary<string, object> with a string key so on. IDataAccessor may support or not support data field identifiers it merely depends on its nature. If an object of user defined class is inserted into the grid, than its property name become the identifiers in the IDataAccessor by default. However, sometimes identifiers may be absent, e.g. if you you use an IList<(Of <(<'T>)>)> object as a parameter of the method Grid.Rows.Add('your object'). In such case, to display data in cells the Wpf GridControl uses indexes of IList<(Of <(<'T>)>)> and index of the column which is calculated when it is inserted into the header.
IDataAccessor is able to subscribe to events of data objects implementing INotifyPropertyChanged interface and transfer them into the grid. This approach is widely used in the event-driven model. Please note, that all implementations of the IDataAccessor interface in the Dapfor's package are thread-safe!
Copy | |
---|---|
//Some data object public class Product : INotifyPropertyChanged { //Some fields private double price; private DateTime maturity; [DoubleConverter(Precision = 3, ShortForm = true, ShowZero = false)] public double Price { get { return price; } set { if (price != value) { price = value; //Notify about color changing if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Price")); } } } } public DateTime Maturity { get { return maturity; } } public event PropertyChangedEventHandler PropertyChanged; } //Using sample public void InitializeGrid(GridControl grid) { //Initialize the grid grid.Headers.Add(new Header()); grid.Headers[0].Add(new Column("Price")); grid.Headers[0].Add(new Column("Maturity")); Console.WriteLine("Current thread: {0}", Thread.CurrentThread.ManagedThreadId); grid.RowUpdated += delegate(object sender, GridControlRowUpdateEventArgs e) { int threadId = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("The data object has been updated. Row = {0}, Field = {1}, Value = {2}, Thread = {3}", e.Row.VisibleIndex, e.DataField.Id, e.DataField.Value, threadId); }; //Add data object to the grid. The object will be implicitly wrapped by the DataObjectAccessor class Product product = new Product(); grid.Rows.Add(product); //The object will notify the grid through the INotifyPropertyChanged, and the grid will automatically //invalidate, sort, filter and highlight the affected cells. product.Price = 12.34; //Notify the grid from the non-GUI thread ThreadPool.QueueUserWorkItem(delegate { int threadId = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Update data object from non-GUI thread (Thread = {0})", threadId); //If the call comes from the non-GUI thread, the grid will synchronize them without blocking the calling thread. product.Price = 25.66; }); } //Console output: Current thread: 7 The data object has been updated. Row = 0, Field = Price, Value = 12,34, Thread = 7 Update data object from non-GUI thread (Thread = 9) The data object has been updated. Row = 0, Field = Price, Value = 25,66, Thread = 7 |