Silverlight:雙向繫結綜合應用-多集合的依賴綁定

來源:互聯網
上載者:User
這是上一篇“Silverlight:雙向繫結綜合應用-自動更新集合彙總欄位”的續篇。需求情境如下:一個公司,有N個員工,逢年過節時要搞一些抽獎活動,最終要公告收獎名單。"員工"類如下:
namespace CollectionBinding{    /// <summary>    /// 員工類    /// </summary>    public class Employee : NotifyPropertyChangedObject    {        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");            }        }    }}
“員工中獎記錄”類如下:
namespace CollectionBinding{    /// <summary>    /// 員工中獎記錄    /// </summary>    public class EmployeePrize : NotifyPropertyChangedObject    {        private string _employeeName = "";        /// <summary>        /// 中獎員工的名字        /// </summary>        public string EmployeeName        {            get { return _employeeName; }            set { _employeeName = value; OnPropertyChanged("EmployeeName"); }        }        private string _prizeName = "";        /// <summary>        /// 獎品名稱        /// </summary>        public string PrizeName        {            get { return _prizeName; }            set { _prizeName = value; OnPropertyChanged("PrizeName"); }        }    }}
NotifyPropertyChangedObject是一個基類
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));            }        }    }}
錄入中獎員工時,要求“員工的名字”必須從公司的員工中選取,如果發現某位員工在公司的員工庫裡沒有登記,也可以在這個介面上的員工列表中臨時添加。介面原型如下:即:下面網格中的員工“姓名下拉框”資料來源,依賴於上面網格中的員工姓名記錄。(類似資料庫中的主從表關係)為了實現這種綁定,需要建立二個ViewModel類EmployeePrizeViewModel類,用來實現下面一個網格的綁定,代碼如下:
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"); }        }    }}
上面的網格綁定,用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 : NotifyPropertyChangedObject    {        private ObservableCollection<Employee> _employeeCollection = new ObservableCollection<Employee>();        /// <summary>        /// 公司的"員工集合"        /// </summary>        public ObservableCollection<Employee> EmployeeCollection        {            get { return _employeeCollection; }        }        private ObservableCollection<EmployeePrizeViewModel> _employeePrizeViewModelCollection = new ObservableCollection<EmployeePrizeViewModel>();        /// <summary>        /// 中獎名單        /// </summary>        public ObservableCollection<EmployeePrizeViewModel> EmployeePrizeViewModelCollection        {            get { return _employeePrizeViewModelCollection; }                    }        /// <summary>        /// 建構函式        /// </summary>        public CompanyViewModel()        {            _employeeCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(_employeeCollection_CollectionChanged);        }        /// <summary>        /// 員工有“增減”時自動觸發        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void _employeeCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)        {            //重新計算工資總和            computeSalaryTotal();            //每個員工的“工資”屬性變化時,自動觸發指定事件            foreach (var item in _employeeCollection)            {                item.PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);                item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);            }        }        /// <summary>        /// 員工屬性變化時自動調用本方法        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)        {            //如果是"工資"屬性變化,則自動重新計算工資匯總            if (e.PropertyName == "Salary")            {                computeSalaryTotal();            }        }        private void computeSalaryTotal()        {            _salaryTotal = _employeeCollection.Sum(c => c.Salary);            OnPropertyChanged("SalaryTotal");//工資總合重新計算後,向外廣播事件,以便UI能自動更新        }        private int _salaryTotal = 0;        /// <summary>        /// 工資匯總        /// </summary>        public int SalaryTotal        {            get            {                return _salaryTotal;            }        }        public override string ToString()        {            string result = "";            XmlSerializer 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;        }    }}
類圖:

最終介面的Xaml代碼:

<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="0,10,0,0"  Name="dataGrid1" VerticalAlignment="Center" ItemsSource="{Binding EmployeeCollection,Mode=TwoWay}">            <sdk:DataGrid.Columns>                <sdk:DataGridTemplateColumn Header="姓名" Width="100">                    <sdk:DataGridTemplateColumn.CellTemplate>                        <DataTemplate>                            <TextBox Text="{Binding Name,Mode=TwoWay}"  VerticalAlignment="Center" Margin="1"></TextBox>                        </DataTemplate>                    </sdk:DataGridTemplateColumn.CellTemplate>                </sdk:DataGridTemplateColumn>                <sdk:DataGridTemplateColumn Header="工資" Width="100">                    <sdk:DataGridTemplateColumn.CellTemplate>                        <DataTemplate>                            <TextBox Text="{Binding Salary,Mode=TwoWay}"  VerticalAlignment="Center" Margin="1"></TextBox>                        </DataTemplate>                    </sdk:DataGridTemplateColumn.CellTemplate>                </sdk:DataGridTemplateColumn>                <sdk:DataGridTemplateColumn Header="操作">                    <sdk:DataGridTemplateColumn.CellTemplate>                        <DataTemplate>                            <Button Click="RemoveEmployee" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="10,1">-</Button>                        </DataTemplate>                    </sdk:DataGridTemplateColumn.CellTemplate>                </sdk:DataGridTemplateColumn>            </sdk:DataGrid.Columns>        </sdk:DataGrid>        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Margin="5">            <TextBlock VerticalAlignment="Center">工資總合:</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,0,0" Width="300"></Border>        <sdk:DataGrid AutoGenerateColumns="False"  HorizontalAlignment="Center" Margin="0,10,0,0"  Name="dataGrid2" VerticalAlignment="Center" ItemsSource="{Binding EmployeePrizeViewModelCollection,Mode=TwoWay}">            <sdk:DataGrid.Columns>                <sdk:DataGridTemplateColumn Header="姓名" Width="100">                    <sdk:DataGridTemplateColumn.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:DataGridTemplateColumn>                <sdk:DataGridTemplateColumn Header="獎品" Width="100">                    <sdk:DataGridTemplateColumn.CellTemplate>                        <DataTemplate>                            <TextBox Text="{Binding EmployeePrize.PrizeName,Mode=TwoWay}"  VerticalAlignment="Center" Margin="1"></TextBox>                        </DataTemplate>                    </sdk:DataGridTemplateColumn.CellTemplate>                </sdk:DataGridTemplateColumn>                <sdk:DataGridTemplateColumn Header="操作">                    <sdk:DataGridTemplateColumn.CellTemplate>                        <DataTemplate>                            <Button Click="RemoveEmployeePrize" HorizontalAlignment="Center" VerticalAlignment="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="10,2" Click="ShowCompanyViewModel">查看CompanyViewModel內容</Button>        <TextBox  Name="textBox1" Margin="5" Height="200" TextWrapping="Wrap"  ScrollViewer.VerticalScrollBarVisibility="Visible"/>    </StackPanel></UserControl>
後面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)        {            //偽造一些資料,測試綁定            Employee e1 = new Employee() { Name = "張三", Salary = 3000 };            Employee e2 = new Employee() { Name = "李四", Salary = 4000 };            Employee e3 = new Employee() { Name = "楊過", 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 = "楊過", PrizeName = "玄鐵劍" } };            EmployeePrizeViewModel 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>        /// 刪除員工        /// </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>        /// 添加員工        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void AddEmployee(object sender, RoutedEventArgs e)        {            c.EmployeeCollection.Add(new Employee() { Name = "新人", Salary = 1000 });        }        /// <summary>        /// 增加中獎名單        /// </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(empPrizeViewModel);        }        /// <summary>        /// 刪除中獎名單        /// </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();        }    }}
線上示範地址:
http://img.24city.com/jimmy/sl4/collectionbinding/樣本源碼下載:http://files.cnblogs.com/yjmyzz/CollectionBinding.7z

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.