zoukankan      html  css  js  c++  java
  • (翻译)在MVVM模式中打开子窗体(Child Window)

      这篇文章主要展示在Silverlight4的应用程序中,用MVVM模式【编者注:如果你对MVVM模式不太理解,请先去熟悉一下关于这方面的资料】怎么打开一个子窗体(Child Window),怎么向子窗体传值,以及怎么从子窗体返回值到主窗体等等

      我使用的方法不是严格意义上的MVVM模式,因为我实际上在ViewModel中实例化了子窗体,这通常很不方便的。但是在Google上找了好长时间,仅仅找到了打开子窗体的工具包的向导,我认为最好的方法就是亲自去实现它。我期望最方便且有严格意义上的MVVM的解决方案在SilverLight5中能够实现。

      本篇文章只仅仅是一个概念的验证,并且是基于一个最简单的例子。MainPage.xaml文件包含两个TextBox控件,即Name和Address,另外,子窗体和主窗体一样,也有两个的控件。当用户在主窗体输入他们的名字,然后点击按钮,那么子窗体就弹出来。并且显示刚才输入的名字(请看下面的图片)。用户可以在子窗体中输入地址然后点击按钮,返回到主窗体【编者注:子窗体同时关闭】,那么主窗体上的地址框中就会显示刚才在子窗体中输入的地址。【编者注:这样就可以达到主窗体和子窗体之间互相传值】

      实现上面的功能是很简单的,仅仅在View Model工程中创建一个子窗体。然后就可以实现子窗体和主窗体之间传递数据。然后创建每一个TextBox建一个属性,为Button创建Command,这是为了打开和关闭子窗体并且传递属性值。需要注意的是子窗体没有ViewModel,所有的需要实现的业务都在主窗体的ViewModel中实现

      第一步:在ViewModel工程中创建一个子窗体,把它命名为MyChildWindow.xmal.

      第二步:为MainPage创建一个ViewModel层。命名为:MainPage_ViewModel.cs

      第三步:通过MainPage_ViewModel.cs来实现 MainPage.xaml.cs和MyChildWindow.xaml.cs 相互传值。【编者注:下面为各个文件的代码】

      MainPage.xaml.cs:

    代码
    namespace View
    {
        
    public partial class MainPage : UserControl
        {

            
    public MainPage()
            {
                InitializeComponent();
                
    this.DataContext = new MainPage_ViewModel();
             }
         }
    }

     MyChildWindow.xaml.cs:

    代码
    namespace ViewModel
    {
        
    public partial class MyChildWindow : ChildWindow
        {
            
    public MyChildWindow(MainPage_ViewModel ma)
            {
                InitializeComponent();
                
    this.DataContext = ma;
            }

        }
    }

      第四步:在 MainPage_ViewModel.cs为主窗体每个TextBox建属性和ViewModel

    代码
    using System.ComponentModel;
    using System.Collections.ObjectModel;
    using ViewModel; 

    namespace ViewModel
    {
        
    public class MainPage_ViewModel : INotifyPropertyChanged
        {
    //Properties of Mainpage
    private string myNameVM = "";
            
    public string MyNameVM
            {

                
    get { return myNameVM; }
                
    set {
                    myNameVM 
    = value;
                    RaisePropertyChanged(
    "myNameVM");
                }
            }

            
    private string myAddressVM = "";
            
    public string MyAddressVM
            {

                
    get { return myAddressVM; }
                
    set
                {
                    myAddressVM 
    = value;
                    RaisePropertyChanged(
    "MyAddressVM");
                }
            }

    //Properties of ChildWindow
            private string myNameCW = "";
            
    public string MyNameCW
            {

                
    get { return myNameCW; }
                
    set
                {
                    myNameCW 
    = value;
                    RaisePropertyChanged(
    "MyNameCW");
                }
            }

            
    private string myAddressCW = "";
            
    public string MyAddressCW
            {

                
    get { return myAddressCW; }
                
    set
                {
                    myAddressCW 
    = value;
                    RaisePropertyChanged(
    "MyAddressCW");
                }
            }

              
    //EventHandler
            public event PropertyChangedEventHandler PropertyChanged;
            
    private void RaisePropertyChanged(string propertyname)
            {
                
    if (PropertyChanged != null)
                {
                    PropertyChanged(
    thisnew PropertyChangedEventArgs(propertyname));
                }
            }
        }

     }

      第五步:如果以前没有创建这个,你就必须得在ViewModel中创建一个类DelegateCommand,主要是处理Button的命令。因此,你必须创建这个类。代码如下:

    代码
    using System;
    using System.Windows.Input;

    namespace ViewModel
    {
        
    public class DelegateCommand : ICommand //
        {
            
    private Predicate<object> _canExecute;
            
    private Action<object> _method;
            
    public event EventHandler CanExecuteChanged;

            
    public DelegateCommand(Action<object> method)
                : 
    this(method, null)
            {
            }

            
    public DelegateCommand(Action<object> method, Predicate<object> canExecute)
            {
                _method 
    = method;
                _canExecute 
    = canExecute;
            }

            
    public bool CanExecute(object parameter)
            {
                
    if (_canExecute == null)
                {
                    
    return true;
                }

                
    return _canExecute(parameter);
            }

            
    public void Execute(object parameter)
            {
                _method.Invoke(parameter);
            }

            
    protected virtual void OnCanExecuteChanged(EventArgs e)
            {
                var canExecuteChanged 
    = CanExecuteChanged;

                
    if (canExecuteChanged != null)
                    canExecuteChanged(
    this, e);
            }

            
    public void RaiseCanExecuteChanged()
            {
                OnCanExecuteChanged(EventArgs.Empty);
            }
        }
    }

      第六步:在MainPage_ViewModel.cs创建一个Commands,它可以绑定到主窗体和子窗体中的按钮上

    代码
    using System.ComponentModel;
    using
     System.Collections.ObjectModel;
    using
     ViewModel; 

    namespace
     ViewModel
    {
        
    public class
     MainPage_ViewModel : INotifyPropertyChanged
        {
    //Properties of Mainpage

    private string myNameVM = "";
            
    public string
     MyNameVM
            {
                
    get { return
     myNameVM; }
                
    set {myNameVM =
     value;
                    RaisePropertyChanged(
    "myNameVM"
    );
                     }
                }

            
    private string myAddressVM = ""
    ;
            
    public string
     MyAddressVM
            {

                
    get { return
     myAddressVM; }
                
    set

                { myAddressVM 
    = value;
                    RaisePropertyChanged(
    "MyAddressVM"
    );
                }
            }

    //Properties of ChildWindow

            private string myNameCW = "";
            
    public string
     MyNameCW
            {

                
    get { return
     myNameCW; }
                
    set

                {  myNameCW 
    = value;
                    RaisePropertyChanged(
    "MyNameCW"
    );
                }
            }

            
    private string myAddressCW = ""
    ;
            
    public string
     MyAddressCW
            {

                
    get { return
     myAddressCW; }
                
    set

                {  myAddressCW 
    = value;
                    RaisePropertyChanged(
    "MyAddressCW"
    );
                }
            }

             
    //When the button is pressed in MainPage, executes method ExecuteOpenChildWindow

            private DelegateCommand _openChildWindow;
            
    public
     DelegateCommand OpenChildWindow
            {
                
    get

                {
                    
    if (_openChildWindow == null)
                        _openChildWindow 
    = new
     DelegateCommand(executeOpenChildWindow);

                    
    return
     _openChildWindow;
                }
            }

            
    // New instance of ChildWindow. Sets the NameProperty of the ChildWindow equal to the Name entered in the MainPage.

            MyChildWindow cw;
            
    private void executeOpenChildWindow(object
     parameter)
            {
                cw 
    = new MyChildWindow(this
    );
                MyNameCW 
    =
     MyNameVM;
                cw.Show();
            }

          
    //When OK-button is pressed in ChildWindow

            private DelegateCommand _okChildWindow;
            
    public
     DelegateCommand OkChildWindow
            {
                
    get
     {
                    
    if (_okChildWindow == null
    )
                        _okChildWindow 
    = new
     DelegateCommand(OkSaveChildWindow);

                    
    return
     _okChildWindow;
                }
            }
            
    //MainPage Address property is set to the value entered in the address textbox in Child Window. Child Window is closed.

            private void OkSaveChildWindow(object parameter)
            {
                MyAddressVM 
    =
     MyAddressCW;
                cw.Close();
            }

              
    //EventHandler

            public event PropertyChangedEventHandler PropertyChanged;
            
    private void RaisePropertyChanged(string
     propertyname)
            {
                
    if (PropertyChanged != null
    )
                {
                    PropertyChanged(
    thisnew
     PropertyChangedEventArgs(propertyname));
                }
            }
      }
    }

      第七步:在MainPage.xaml 和 MyChildWindow.xaml中分别新增两个TextBox,然后把他们分别绑定到MainPage_ViewModel中的属性上。然后再分别建一个按钮,绑定到Command上

    MainPage.xaml

    代码
    <StackPanel>

            
    <Grid Margin="0 10 0 5" Width="350">

        
    <Grid.RowDefinitions>
            
    <RowDefinition Height="*"/>
            
    <RowDefinition Height="*"/>
            
    <RowDefinition Height="*"/>

        
    </Grid.RowDefinitions>
        
    <Grid.ColumnDefinitions>
            
    <ColumnDefinition Width="150"/>
            
    <ColumnDefinition Width="*"/>

        
    </Grid.ColumnDefinitions>

        
    <!--TextBlocks-->
        
    <TextBlock Text="Name:" TextWrapping="Wrap" Margin="5,5,0,5" Grid.Row="0"  />
        
    <TextBlock Text="Address:" Grid.Row="1" Grid.Column="0"  />

       
    <!--TextBox, where the users enters data. Binds to the properties of MainPage_ViewModel-->
      
    <TextBox Text="{Binding MyNameVM, Mode=TwoWay}" Grid.Row="0" Grid.Column="1"/>
      
    <TextBox Text="{Binding MyAddressVM, Mode=TwoWay}"  Grid.Row="1" Grid.Column="1"/>

        
    <Button Content="Open Child Window"
                VerticalAlignment
    ="Center"
                HorizontalAlignment
    ="left"
                Width
    ="auto"
                Margin
    ="5"
                Grid.Row
    ="2"
                Command
    ="{Binding OpenChildWindow}" <!--Binds to CommandDelegate from the ViewModel -->
            
    />
            
    </Grid>
        
    </StackPanel>
    MyChildWindow.xaml
    代码
    <Grid Margin="0 30 0 5" Width="350">

        
    <Grid.RowDefinitions>
            
    <RowDefinition Height="auto"/>
            
    <RowDefinition Height="auto"/>
            
    <RowDefinition Height="205*"/>

        
    </Grid.RowDefinitions>
        
    <Grid.ColumnDefinitions>
            
    <ColumnDefinition Width="150"/>
            
    <ColumnDefinition Width="*"/>

        
    </Grid.ColumnDefinitions>

        
    <TextBlock Text="Name: " Grid.Row="0" />
        
    <TextBlock Text="Address:" Grid.Row="1" Grid.Column="0"  />

        
    <!-- TextBoxes are bind to the properties from the ViewModel.  -->
        
    <TextBox x:Name="InputName" Text="{Binding MyNameCW, Mode=TwoWay}" Grid.Row="0" Grid.Column="1" Height="20"/>
        
    <TextBox x:Name="OutputAddress" Text="{Binding MyAddressCW, Mode=TwoWay}" Grid.Row="1" Grid.Column="1" Height="20"/>

       
    <!-- Button comand bind to CommandDelegate from ViewModel -->
      
    <Button x:Name="OKButton" Command="{Binding OkChildWindow}" Content="OK" Width="75" Height="23" Margin="0,12,79,0" Grid.Row="2" Grid.Column="1"/>
    </Grid>

      翻译的不足之处,请多多指教。原文地址http://mariaevert.dk/thesis/?p=710

  • 相关阅读:
    Git学习笔记
    排序篇
    c++面试(二)
    c++面试(一)
    maven在mac上的入门使用
    win7系统下安装centos6.6
    Centos6.6下安装oracle 11g教程
    TCP连接的三次握手和四次解散过程
    IP地址划分
    PriorityQueue优先队列用法入门
  • 原文地址:https://www.cnblogs.com/888h/p/1900149.html
Copyright © 2011-2022 走看看