Silverlight: bidirectional binding of integrated applications-dependency binding for multiple sets

Source: Internet
Author: User
This is the last article "Silverlight: bidirectional binding of integrated applications-automatic update of collection summary fields. The requirements are as follows: a company with N employees will have some lottery activities during the holidays, and finally the prize receiving list will be announced. The "employee" category is as follows:
Namespace collectionbinding {// <summary> // employee class // </Summary> public class employee: policypropertychangedobject {private string _ name = ""; public string name {set {_ name = value; onpropertychanged ("name") ;}get {return _ name ;}} private int _ salary = 0; public int salary {get {return _ salary;} set {_ salary = value; onpropertychanged ("salary ");}}}}
The "Employee winning record" category is as follows:
Namespace collectionbinding {// <summary> // employee winning record // </Summary> public class employeeprize: policypropertychangedobject {private string _ employeename = ""; /// <summary> /// name of the winning employee /// </Summary> Public String employeename {get {return _ employeename;} set {_ employeename = value; onpropertychanged ("employeename");} private string _ prizename = ""; /// <summary> // prize name // </Summary> Public String prizename {get {return _ prizename;} set {_ prizename = value; onpropertychanged ("prizename ");}}}}
Notifypropertychangedobject is a base class
using System.ComponentModel;namespace CollectionBinding{    public class NotifyPropertyChangedObject : INotifyPropertyChanged    {        public NotifyPropertyChangedObject()        {        }        public event PropertyChangedEventHandler PropertyChanged;        protected void OnPropertyChanged(string propertyName)        {            if (PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));            }        }    }}
When a winning employee is entered, the "employee name" must be selected from the company's employees. If an employee is not registered in the company's employee inventory, you can also temporarily add it to the employee list on this interface. The following figure shows a prototype: the "Name drop-down box" data source of employees in the following Grid depends on the employee name records in the preceding grid. (Similar to the relationship between the master and slave tables in the database) to implement this binding, you need to create two viewmodel classes, the employeeprizeviewmodel class, to bind the following mesh. The Code is as follows:
using System.ComponentModel;using System.Collections.ObjectModel;namespace CollectionBinding{    public class EmployeePrizeViewModel : NotifyPropertyChangedObject    {        private ObservableCollection<Employee> _employees = new ObservableCollection<Employee>();        public ObservableCollection<Employee> Employees        {            get { return _employees; }            set { _employees = value; OnPropertyChanged("Employees"); }        }        private EmployeePrize _employeePrize = new EmployeePrize();        public EmployeePrize EmployeePrize        {            get { return _employeePrize; }            set { _employeePrize = value; OnPropertyChanged("EmployeePrize"); }        }    }}
The above mesh binding is implemented using companyviewmodel.
Using system. collections. objectmodel; using system. collections. specialized; using system. componentmodel; using system. io; using system. LINQ; using system. text; using system. XML. serialization; namespace collectionbinding {public class companyviewmodel: yypropertychangedobject {private observablecollection <employee> _ employeecollection = new observablecollection <employee> (); /// <summary> /// company's "Employee Collection" /// </Summary> Public observablecollection <employee> employeecollection {get {return _ employeecollection ;}} private observablecollection <employeeprizeviewmodel> _ employeeprizeviewmodelcollection = new observablecollection <employeeprizeviewmodel> (); /// <summary> /// winning list /// </Summary> Public observablecollection <employeeprizeviewmodel> employeeprizeviewmodelcollection {get {return _ employeeprizeviewmodelcollection ;}} /// <summary> /// constructor /// </Summary> Public companyviewmodel () {_ employeecollection. collectionchanged + = new notifycollectionchangedeventhandler (_ employeecollection_collectionchanged );} /// <summary> /// triggered automatically when an employee has "increased or decreased" /// </Summary> /// <Param name = "sender"> </param>/ // <Param name = "E"> </param> private void _ employeecollection_collectionchanged (Object sender, notifycollectionchangedeventargs e) {// recalculates the sum of wages computesalarytotal (); // when the "salary" attribute of each employee changes, the specified event foreach (VAR item in _ employeecollection) is automatically triggered) {item. propertychanged-= new propertychangedeventhandler (item_propertychanged); item. propertychanged + = new propertychangedeventhandler (item_propertychanged );}} /// <summary> /// call this method automatically when the employee attributes change /// </Summary> /// <Param name = "sender"> </param>/ // <Param name = "E"> </param> private void item_propertychanged (Object sender, propertychangedeventargs e) {// if the "salary" attribute changes, the system automatically recalculates the salary summary if (E. propertyname = "salary") {computesalarytotal () ;}} private void computesalarytotal () {_ salarytotal = _ employeecollection. sum (C => C. salary); onpropertychanged ("salarytotal"); // After the sum of wages is recalculated, events are broadcast externally so that the UI can be automatically updated} private int _ salarytotal = 0; /// <summary> /// salary summary /// </Summary> Public int salarytotal {get {return _ salarytotal ;}} public override string tostring () {string result = ""; xmlserializer = new xmlserializer (typeof (companyviewmodel); Using (memorystream MS = new memorystream () {try {xmlserializer. serialize (MS, this); Result = encoding. utf8.getstring (Ms. toarray (), 0, (INT) ms. length) ;}catch {}} return result ;}}}
Class diagram:

The final interface's XAML code:

<Usercontrol X: class = "collectionbinding. mainpage "xmlns =" http://schemas.microsoft.com/winfx/2006/xaml/presentation "xmlns: x =" http://schemas.microsoft.com/winfx/2006/xaml "xmlns: D =" http://schemas.microsoft.com/expression/blend/2008 "xmlns: MC =" http://schemas.openxmlformats.org/markup-compatibility/2006 "MC: ignorable =" D "D: designheight = "300" D: designwidth = "400" xmlns: SDK = "http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <stackpanel X: Name = "layoutroot" background = "white"> <SDK: dataGrid autogeneratecolumns = "false" horizontalalignment = "center" margin = "," name = "datagrid1" verticalignment = "center" itemssource = "{binding employeecollection, mode = twoway} "> <SDK: DataGrid. columns> <SDK: Maid header = "name" width = "100"> <SDK: maid. celltemplate> <datatemplate> <textbox text = "{binding name, mode = twoway} "verticalalignment =" center "margin =" 1 "> </textbox> </datatemplate> </SDK: datagridtemplatecolumn. celltemplate> </SDK: Maid> <SDK: Maid header = "width" width = "100"> <SDK: maid. celltemplate> <datatemplate> <textbox text = "{binding salary, mode = twoway} "verticalalignment =" center "margin =" 1 "> </textbox> </datatemplate> </SDK: datagridtemplatecolumn. celltemplate> </SDK: Maid> <SDK: Maid header = "operation"> <SDK: maid. celltemplate> <datatemplate> <button click = "removeemployee" horizontalalignment = "center" verticalignment = "center" padding = "10, 1">-</button> </datatemplate> </SDK: datagridtemplatecolumn. celltemplate> </SDK: datagridtemplatecolumn> </SDK: DataGrid. columns> </SDK: DataGrid> <stackpanel horizontalalignment = "center" orientation = "horizontal" margin = "5"> <textblock verticalignment = "center"> total salary: </textblock> <textblock text = "{binding salarytotal, mode = twoway}" margin = "5, 0, 5, 0 "width =" 60 "> </textblock> </stackpanel> <button click =" addemployee "padding =" 10, 1 "margin =" 5 "horizontalalignment =" center "> + </button> <border borderbrush = "black" borderthickness = "0, 1, 300 "width =" "> </Border> <SDK: DataGrid autogeneratecolumns =" false "horizontalalignment =" center "margin =, 0, 0 "name =" datagrid2 "verticalignment =" center "itemssource =" {binding employeeprizeviewmodelcollection, mode = twoway} "> <SDK: DataGrid. columns> <SDK: Maid header = "name" width = "100"> <SDK: maid. celltemplate> <datatemplate> <ComboBox itemssource = "{binding employees, mode = twoway}" selectedvaluepath = "name" selectedvalue = "{binding employeeprize. employeename, mode = twoway} "> <ComboBox. itemtemplate> <datatemplate> <stackpanel orientation = "horizontal"> <textblock text = "{binding name}"> </textblock> </stackpanel> </datatemplate> </ComboBox. itemtemplate> </ComboBox> </datatemplate> </SDK: datagridtemplatecolumn. celltemplate> </SDK: Maid> <SDK: Maid header = "prize" width = "100"> <SDK: maid. celltemplate> <datatemplate> <textbox text = "{binding employeeprize. prizename, mode = twoway} "verticalignment =" center "margin =" 1 "> </textbox> </datatemplate> </SDK: datagridtemplatecolumn. celltemplate> </SDK: Maid> <SDK: Maid header = "operation"> <SDK: maid. celltemplate> <datatemplate> <button click = "removeemployeeprize" horizontalalignment = "center" verticalignment = "center" padding = "10, 1">-</button> </datatemplate> </SDK: datagridtemplatecolumn. celltemplate> </SDK: datagridtemplatecolumn> </SDK: DataGrid. columns> </SDK: dataGrid> <button click = "addemployeeprize" padding = "10, 1" margin = "5" horizontalalignment = "center"> + </button> <button horizontalalignment = "center" padding =" 200 "Click =" showcompanyviewmodel "> View companyviewmodel content </button> <textbox name =" textbox1 "margin =" 5 "Height =" "textwrapping =" Wrap "scrollviewer. verticalscrollbarvisibility = "visible"/> </stackpanel> </usercontrol>
The following section of XAML. CS:
Using system. windows; using system. windows. controls; namespace collectionbinding {public partial class mainpage: usercontrol {companyviewmodel c = new companyviewmodel (); Public mainpage () {initializecomponent (); this. loaded + = new routedeventhandler (mainpage_loaded);} void mainpage_loaded (Object sender, routedeventargs e) {// forge some data and test the binding of employee e1 = new employee () {name = "James", salary = 3000 }; Employee e2 = new employee () {name = "Li Si", salary = 4000}; employee E3 = new employee () {name = "Yang Guo ", salary = 9999}; C. employeecollection. add (E1); C. employeecollection. add (E2); C. employeecollection. add (E3); employeeprizeviewmodel p1 = new employeeprizeviewmodel () {employees = C. employeecollection, employeeprize = new employeeprize () {employeename = "Yang Guo", prizename = "" }}; employeepr Izeviewmodel P2 = new employeeprizeviewmodel () {employees = C. employeecollection, employeeprize = new employeeprize () {employeename = "", prizename = "ThinkPad x220" }}; C. employeeprizeviewmodelcollection. add (P1); C. employeeprizeviewmodelcollection. add (P2); this. datacontext = C ;} /// <summary> /// Delete employee /// </Summary> /// <Param name = "sender"> </param> /// <Param name = "E"> </param> private void Removeemployee (Object sender, routedeventargs e) {var EMP = (sender as button). datacontext as employee; If (EMP! = NULL) {C. employeecollection. remove (EMP );}} /// <summary> /// add employee /// </Summary> /// <Param name = "sender"> </param> /// <Param name = "E"> </param> private void addemployee (Object sender, routedeventargs e) {C. employeecollection. add (new employee () {name = "newcomer", salary = 1000 });} /// <summary> /// Add the winning list /// </Summary> /// <Param name = "sender"> </param> /// <Param name = "E"> </param> private void Addemployeeprize (Object sender, routedeventargs e) {var empprizeviewmodel = new employeeprizeviewmodel () {employees = C. employeecollection}; var empprize = new employeeprize (); If (C. employeecollection. count> 0) {empprize. employeename = C. employeecollection [C. employeecollection. count-1]. name;} empprizeviewmodel. employeeprize = empprize; C. employeeprizeviewmodelcollection. add (empprizeviewmo Del );} /// <summary> /// Delete the winning list /// </Summary> /// <Param name = "sender"> </param> /// <Param name = "E"> </param> private void removeemployeeprize (Object sender, routedeventargs e) {var empprizeviewmodel = (sender as button ). datacontext as employeeprizeviewmodel; If (empprizeviewmodel! = NULL) {C. employeeprizeviewmodelcollection. Remove (empprizeviewmodel);} private void showcompanyviewmodel (Object sender, routedeventargs e) {This. textbox1.text = C. tostring ();}}}
Online Demo address:
Bytes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.