Aquí hay un ejemplo que vincula un objeto y algunos antepasados a la interfaz de usuario; el uso de C# 3.0 aquí es puramente breve - todo funcionaría también con C# 2.0.
La mayor parte del código aquí es la creación de la forma, y / o tratar con las notificaciones de cambio de propiedad - importante, no hay ningún código dedicado a la actualización de la interfaz de usuario del modelo de objetos o el modelo de objetos desde la interfaz de usuario.
Tenga en cuenta también el IDE puede hacer un montón de código de enlace de datos para usted, simplemente dejando caer una BindingSource en la forma y establecer el origen de datos a través de un tipo el cuadro de diálogo en la cuadrícula de propiedades.
Tenga en cuenta que no es esencial para proporcionar notificaciones de cambio de propiedad (las cosas PropertyChanged) - sin embargo, más de 2 vías IU unión funcionará mucho mejor si lo hace implementar esto. No es que PostSharp tenga algunas formas interesantes de hacerlo con un código mínimo.
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<Order> Orders { get; set; } // XmlSerializer demands setter
public Customer() {
Orders = new List<Order>();
}
}
[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<T>(ref T field, T value, string propertyName) {
if (!EqualityComparer<T>.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));
}
}
gracias por el código, parece que esto responde mi pregunta, intentaré implementar tal solución y veré si puedo tener éxito. He visto postsharp, pero no estoy seguro de si es una buena manera de hacerlo o no. –
TreeViews son un dolor, nota –