Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here's an example that binds an object and some ancestors to the UI; the use of C# 3.0 here is purely for brevity - everything would work with C# 2.0 too.</p> <p>Most of the code here is setting up the form, and/or dealing with property-change notifications - importantly, there isn't any code devoted to updating the UI from the object model, or the object model from the UI.</p> <p>Note also the IDE can do a lot of the data-binding code for you, simply by dropping a BindingSource onto the form and setting the DataSource to a type via the dialog in the property grid.</p> <p>Note that it isn't essential to provide property change notifications (the PropertyChanged stuff) - however, most 2-way UI binding will work considerably better if you do implement this. Not that PostSharp has some interesting ways of doing this with minimal code.</p> <pre><code>using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Windows.Forms; using System.Xml.Serialization; static class Program { // formatted for vertical space [STAThread] static void Main() { Application.EnableVisualStyles(); Button load, save, newCust; BindingSource source = new BindingSource { DataSource = typeof(Customer) }; XmlSerializer serializer = new XmlSerializer(typeof(Customer)); using (Form form = new Form { DataBindings = {{"Text", source, "Name"}}, // show customer name as form title Controls = { new DataGridView { Dock = DockStyle.Fill, // grid of orders DataSource = source, DataMember = "Orders"}, new TextBox { Dock = DockStyle.Top, ReadOnly = true, // readonly order ref DataBindings = {{"Text", source, "Orders.OrderRef"}}}, new TextBox { Dock = DockStyle.Top, // editable customer name DataBindings = {{"Text", source, "Name"}}}, (save = new Button { Dock = DockStyle.Bottom, Text = "save" }), (load = new Button{ Dock = DockStyle.Bottom, Text = "load"}), (newCust = new Button{ Dock = DockStyle.Bottom, Text = "new"}), } }) { const string PATH = "customer.xml"; form.Load += delegate { newCust.PerformClick(); // create new cust when loading form load.Enabled = File.Exists(PATH); }; save.Click += delegate { using (var stream = File.Create(PATH)) { serializer.Serialize(stream, source.DataSource); } load.Enabled = true; }; load.Click += delegate { using (var stream = File.OpenRead(PATH)) { source.DataSource = serializer.Deserialize(stream); } }; newCust.Click += delegate { source.DataSource = new Customer(); }; Application.Run(form); } } } [Serializable] public sealed class Customer : NotifyBase { private int customerId; [DisplayName("Customer Number")] public int CustomerId { get { return customerId; } set { SetField(ref customerId, value, "CustomerId"); } } private string name; public string Name { get { return name; } set { SetField(ref name, value, "Name"); } } public List&lt;Order&gt; Orders { get; set; } // XmlSerializer demands setter public Customer() { Orders = new List&lt;Order&gt;(); } } [Serializable] public sealed class Order : NotifyBase { private int orderId; [DisplayName("Order Number")] public int OrderId { get { return orderId; } set { SetField(ref orderId, value, "OrderId"); } } private string orderRef; [DisplayName("Reference")] public string OrderRef { get { return orderRef; } set { SetField(ref orderRef, value, "OrderRef"); } } private decimal orderValue, carriageValue; [DisplayName("Order Value")] public decimal OrderValue { get { return orderValue; } set { if (SetField(ref orderValue, value, "OrderValue")) { OnPropertyChanged("TotalValue"); } } } [DisplayName("Carriage Value")] public decimal CarriageValue { get { return carriageValue; } set { if (SetField(ref carriageValue, value, "CarriageValue")) { OnPropertyChanged("TotalValue"); } } } [DisplayName("Total Value")] public decimal TotalValue { get { return OrderValue + CarriageValue; } } } [Serializable] public class NotifyBase { // purely for convenience [field: NonSerialized] public event PropertyChangedEventHandler PropertyChanged; protected bool SetField&lt;T&gt;(ref T field, T value, string propertyName) { if (!EqualityComparer&lt;T&gt;.Default.Equals(field, value)) { field = value; OnPropertyChanged(propertyName); return true; } return false; } protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload