WPF外包團隊技術分享—WPF的MVVM架構解析(分享)

 

我們前面一節白話白眼,都只是從概念上了解了mvvm,瞭解和做還是差距很大,所以我們同樣需要親自動手實驗來真的弄懂mvvm。
       例子就取一個生活中的,用mvvm模式完成家庭的操作,比如顯示查詢家庭成員,增加家庭成員(娶妻生子等),減少家庭成員(嫁女老去等).
       確定好這個例子我們就需要先準備一下數據,我們首先想到可能是用數據庫,不過silverlight是瀏覽器客戶端的東西,是不能和你以前使用asp.net一樣主動直接連接數據庫的,如果你真的要開始就連接數據庫,你還得準備另外學習一些知識。
       我們先構思一下自己的類的樣子:
         class familymember
          {
               public string Name{get,set;}//姓名
               public string Sex{get,set;}//性別(不使用bool,因爲現在有中性人了)
               public string Title{get,set;}//稱謂
               public int    Age{set,get;}//年齡
          }

       然後我們就可以開始工作,打開vs2010 創建一個silverlight應用程序 family.sln.進入設計界面,照着步驟往下,想不明白也別管,到了最後你就完全明白了。
1.在解決方案管理按MVVM的模式新建Views、Models、viewmodels、commands文件夾,這個不是必須的,但是真正做項目的時候是必須,你的組織你的程序文件啊!否則成百上千的文件,你要找個文件都得找成近視眼;
2.在models文件夾下新建一個類familymember.cs,照抄上面的;
        public class familymember//家庭成員類
        {
             public string Name{get;set;}--姓名
             public string Sex{get;set;}--性別(不使用bool,因爲現在有中性人了)
             public string Title{get;set;}--稱謂
             public int    Age{set;get;}--年齡
        }
3.繼續在models文件下再新建一個類family.cs,當然你可以不另外創建,直接寫在familymember.cs裏面
         using System.Collections.Generic; //List類在此名稱空間下
         public class family//家庭類(就是familymember類的集合)
         public class family
            {
                 private List<familymember> _family;
                 public List<familymember> initfamily()
                     {
                        _family = new List<familymember>()
                           {
                                new familymember{Name="王大爺",Age=120,Sex="男",Title="太爺"},
                                new familymember{Name="王老爺",Age=80,Sex="男",Title="爺爺"},
                                new familymember {Name="王中錢",Age=50,Sex="男",Title="老爸"},
                                new familymember {Name="王夫人",Age=48,Sex="女",Title="老媽"},
                                new familymember {Name ="王大二",Age=25,Sex="男",Title="大兒子"},
                                new familymember {Name="王八蛋",Age=20,Sex="男",Title="小兒子"},
                                new familymember {Name ="王小妹",Age=18,Sex="女",Title="小女兒"}
                           };
                          return _family ;
                  }

               }

4.設計我們的viewmodel文件,在viemodels文件夾下我們新建一個familyviewmodel.cs類
                 public class familymodelview
                 {
                   public List<familymember> myfamily { get; set; }
                   public familymodelview()
                 {
                       //構造函數中初始化家庭成員列表
                       myfamily = new family().initfamily();
                  }
                  }
5.在views下面建一個文件familyview.xaml,這個是用來顯示家庭成員的;
        <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions >
            <RowDefinition Height="auto"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" >
        <TextBlock Text="輸入查詢條件"/>
        <TextBox Name="txtsearch" Width="100" Height="23"/>
         <Button Name="btnsearch" Content="查詢"/>
         <Button Name="btnadd" Content="添加"/>
         <Button Name="btndel" Content="刪除"/>
        </StackPanel>
        <sdk:DataGrid Grid.Row="1" Width="300" Name="mygrid"   ItemsSource="{Binding myfamily}"     HorizontalAlignment="Left" IsReadOnly="True">
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Binding="{Binding Name}" Header="姓名" Width="80"/>
                <sdk:DataGridTextColumn Binding="{Binding Title}" Header="稱謂" Width="80"/>
                <sdk:DataGridTextColumn Binding="{Binding Sex}" Header="性別" Width="50"/>
                <sdk:DataGridTextColumn Binding="{Binding Age}" Header="年齡" Width="50"/>
                <sdk:DataGridTemplateColumn x:Name="c1" Header="刪除" >
                    <sdk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Name="btndelete" Content="Del" Click="btndelete_Click"/>
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellTemplate>
                </sdk:DataGridTemplateColumn>
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>

    </Grid>
6.開始拼裝,在Mainpage.xaml文件中寫上
       <Grid x:Name="LayoutRoot" Background="White" >
             <local:familyview/>
        </Grid>
      同時在cs文件中,將mainpage的構造函數修改一下:
       public MainPage()
          {
            InitializeComponent();
            this.LayoutRoot.DataContext = new familymodelview();
          }
7.運行一下,是不是看見了家庭成員列表。比起以前的asp.net開發是不是很繁雜啊,一點都不習慣啊!例子到這裏好像還是沒有看出太大的端倪,但應該可以看出view文件已經很白了,我們繼續往下。

8.現在王小二娶了媳婦董雨進門,那麼這個家庭列表就增加了,我們需要添加方法,如果是asp.net,在view.cs文件調用一下解決了,但這樣那個xaml文件又複雜了,理性人和感性人又得糾結了。在mvvm中這個要玩的是familymodelview.cs這個文件。添加一個addmember方法
      public void addmember(familymember p)
     {
          MessageBox.Show("恭喜,你的家庭成員增加了");
     }

    同時我們把查詢和刪除的方法也添加上.......
9.方法添加完了,我們需要把這個方法綁定到view裏面的添加按鈕上,這個時候就需要用到Icommand接口了。在commad下建一個relaycommand.cs
    public class relaycommand:ICommand
      {
        private bool _isenabled;
        private Action _handler;
        public relaycommand(Action handler)
        {
            handler = _handler;
        }
        public bool IsEnabled
        {
            get { return _isenabled; }
            set
            {
                _isenabled = value;
                if (CanExecuteChanged != null)
                {
                    this.CanExecuteChanged(this, EventArgs.Empty);
                }
            }
        }
        public bool CanExecute(object parameter)
        {
            //throw new NotImplementedException();
            return IsEnabled;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            //throw new NotImplementedException();
            _handler();
        }
    }
10.回到familymodelview.cs裏面添加上一些語句,完整程序的如下
        public List<familymember> myfamily { get; set; }
        public string searchtext { get; set; }//這個是用於和那個搜索條件綁定用的
        private ICommand _addfamilymembercommand;
        private ICommand _deletefamilymembercommand;
        private ICommand _searchmembercommand;
        public ICommand addfamilymembercommand
        {
            get { return _addfamilymembercommand; }
        }
        public ICommand deletefamilymembercommand
        {
            get { return _deletefamilymembercommand; }
        }
        public ICommand searchmembercommand
        {
            get { return _searchmembercommand; }
        }

        //構造函數
        public familymodelview()
        {
            myfamily = new family().initfamily();
            _searchmembercommand = new relaycommand(searchfamilymember) { IsEnabled = true };
            _addfamilymembercommand = new relaycommand(addfamilymember) { IsEnabled = true };
            _deletefamilymembercommand = new relaycommand(removefamilymember) { IsEnabled = true };
        }
        //實現功能的方法
        public void addfamilymember()
        {
            MessageBox.Show("恭喜,你的家庭成員增加了");
        }
        public void removefamilymember()
        {

            MessageBox.Show("sorry,你的家庭成員減少了");
        }
        public void searchfamilymember()
        {
            List<familymember> mylists = null;
            if (!string.IsNullOrEmpty(searchtext))
            {
                mylists = new List<familymember>();
                foreach (familymember p in myfamily)
                {
                    if (p.Name.Contains(searchtext))
                        mylists.Add(p);
                }
                myfamily = mylists;
            }
          
        }
    }
10.這個時候回到view界面,程序再狠,也不可能知道藝術家在xaml文件中發揮到天上還是地上,所以作爲程序員的你還需要在多廢點腦細胞,誰讓你能呢!如果說view是個美人,那viewmodel是view背後的那個男人,view要發揮作用是離不開viewmodel的,在view的cs文件中寫上:
      public partial class familyview : UserControl
       {
            familymodelview family1 = new familymodelview();
            public familyview()
             {
                InitializeComponent();

              }

        private void btndelete_Click(object sender, RoutedEventArgs e)
        {
           family1.
        }

        private void btnsearch_Click(object sender, RoutedEventArgs e)
        {
            family1.searchtext = this.txtsearch.Text.Trim();
            family1.searchmembercommand.Execute(null );
        }
    }
運行一下看看,點擊添加和刪除,是不是提示成功了。別以爲到這裏就真的會了mvvm,仔細想想,是不是有一點感覺:繞老繞去的寫了好多代碼其實都是在做無用功,特別是那個Icommand接口。如果你這麼想,就說明你真的用心學了。
11.真諦:如果mvvm是象上面那樣寫程序,那還不如不要呢!記得前面我們白話的時候提過,view就像美女一樣,基本靠“綁”,所以刪除我們的哪些語句,讓click事件滾蛋,直接在view的xaml文件中把命令綁上去。代碼如下:
            <Button Name="btnsearch" Content="查詢" Command="{Binding searchmembercommand}"/>
            <Button Name="btnadd" Content="添加" Command="{Binding addfamilymembercommand}" />
            <Button Name="btndel" Content="刪除" Command="{Binding deletefamilymembercommand}" />
12.再次運行,看看是不是一樣的效果。現在你應該明白這種模式的優勢了吧,界面設計和程序設計者之間的自由度是不是發揮到了極致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章