Bernhard  GrojerSilverlight: DataBinding zu WCF Service - Teil 2/2



Im letzten Posting haben wir mithilfe von Silverlight und WCF Daten am Client verfügbar gemacht. Außerdem haben wir bereits deklaratives DataBinding verwendet in XAML.

Nun wollen wir noch dafür sorgen, dass der Client Änderungen in den (Customer) Objekten mitprotokolliert und diese später mittels WCF wieder an den Server gesendet / gespeichert werden können.

Da wir bereits Objekte gegen unser DataGrid gebunden haben werden die Änderungen auch zurück ins Objekt gespeichert (TWO-WAY DataBinding)

Unsere CustomerDataSource Klasse muss nun nur noch geänderte “Kunden” mitprotokollieren.

Dafür können wir den selben Ansatz verwenden, den auch Silverlight/WPF für die akt. des UI verwendet oder auch der LINQ DataContext dies macht.
Wir hängen uns an das PropertyChanged Event (vom Interface INotifyPropertyChanged) und lassen uns Informieren sobald eine Änderung erfolgt:

 Dictionary<Customer, string> _ChangedObjects = new Dictionary<Customer, string>();
        public void RegisterChangeTracking(Customer c)
        {
            c.PropertyChanged += (sender, e) => 
                { 
                    var cus = sender as Customer;
                    if (_ChangedObjects.ContainsKey(cus))
                        _ChangedObjects[cus] += ";" + e.PropertyName;
                    else
                        _ChangedObjects.Add(cus, e.PropertyName);
                };
        }

Bevor nun ein Objekt in die Observable<T> Liste wandert (und somit im UI dargestellt wird) wird es mithilfe von RegisterChangeTracking T o) registriert.
Ändert sich nun ein Property in der Klasse wird ein Eintrag im _ChangedObjects Dictionary erstellt.

private void LoadCustomers()
        {
            CustomerServiceClient client = new CustomerServiceClient();
            client.GetCustomersCompleted += (sender, e) =>
            {
                foreach (var c in e.Result)
                {
                    _Customers.Add(c);
                    RegisterChangeTracking(c);
                }

            };
            client.GetCustomersAsync();
        }

Nun müssen wir nur noch das Dictionary mit den geänderten Daten dem WCF Service übergeben.

private void SaveCustomers()
        {
            CustomerServiceClient client = new CustomerServiceClient();
            client.SaveCustomersCompleted += (sender, e) =>
            {
                var b = e.Result;
            };
            client.SaveCustomersAsync(_ChangedObjects);
        }

Die Methode SaveCustomer wird nun aus der Silverlight-Anwendung aufgerufen (ein Button im UI triggert folgenden Code):

private CustomerDataSource CustomerDataSource
        {
            get
            {
                return this.Resources["Customers"] as CustomerDataSource;
            }
        }

        private void ButtonSave_Click(object sender, RoutedEventArgs e)
        {
            CustomerDataSource.Save();
        }


Damit ist die Client-Seite abgeschlossen und wir müssen uns nun noch um das tatsächliche Speichern in der CustomerService Klasse kümmern.

Hier möchten wir natürlich Datenbankabfragen minimieren und soviel wie möglich mit einem gang zur Datenbank ausführen.
Außerdem sollen nur die Felder gespeichert werden, die tatsächlich geändert wurden:

public bool SaveCustomers(Dictionary<Customer, string> Customers)
        {
            using (var DB = new NorthwindDataContext())
            {
                var query = from c in DB.Customers
                            where Customers.Keys.Select(cus => cus.CustomerID).Contains(c.CustomerID)
                            select c;

                var lst = query.ToList();
                Type t = typeof(Customer);
                foreach (var kv in Customers)
                {
                    var oldCustomer = kv.Key;
                    var newCustomer = lst.Single(cus => cus.CustomerID == oldCustomer.CustomerID);

                    foreach (var s in kv.Value.Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries))
                    {
                        var propInfo = t.GetProperty(s);
                        var v = propInfo.GetValue(oldCustomer, null);
                        propInfo.SetValue(newCustomer, v,null);
                    }
                }

                DB.SubmitChanges();
            }
            return true;
        }

Das fertige Beispiel (selber Link wie im Teil 1 d. Blog-Serie) steht zum Download bereit: SilverlightConsumeWCF 08042009.zip



Kategorien: 09.04.2009 08:43:56


 


Neuen Kommentar einfügen:

  Titel:   
  Name:
  E-Mail:
  Kommentar:

 
 


Kommentare




© Copyright 2008 ppedv AG