WPF MVVM

文章介绍了在WPF应用中使用MVVM设计模式进行解耦的一个例子。通过LoginModel(模型)、LoginVM(视图模型)和MainWindow(视图)的交互,展示了如何实现数据绑定和命令处理。LoginVM作为桥梁,连接了M和V,使得业务逻辑与界面展示分离,提高了代码的可维护性。
摘要由CSDN通过智能技术生成

这是一种设计模式
解耦的过程
M:model 数据模型
V: view 界面
VM: ViewModel 整合业务的过程


M的实例

public partial class MainWindow : Window
    {
        LoginModel loginModel;
        public MainWindow()
        {
            InitializeComponent();

            loginModel = new LoginModel();
            // 将数据绑定的必要操作 loginModel里面有UserName和Password
            this.DataContext = loginModel;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

            if (loginModel.UserName == "wpf" && loginModel.Password == "666")
            {
                //弹出新的界面
                Index index = new Index();
                index.Show();

                //隐藏当前界面
                this.Hide();
            }
            else
            {
                //弹出一个警告框
                MessageBox.Show("输入的用户名或密码不正确");

                loginModel.UserName = "";
                loginModel.Password = "";
            }
        }
    }
	
	//
	//这里是如何将M提出来的
	//
    public class LoginModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handle = PropertyChanged;
            if (handle != null)
            {
                handle(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        // 这里写法也固定,接收账号密码
        private string _UserName;
        public string UserName
        {
            get { return _UserName; }
            set { _UserName = value; RaisePropertyChanged("UserName"); }
        }

        private string _Password;
        public string Password
        {
            get { return _Password; }
            set { _Password = value; RaisePropertyChanged("Password"); }
        }
    }

M和VM的分离(未完全版)
创建LoginModel(这是M)

public class LoginModel
    {
        // 这里写法也固定,接收账号密码
        private string _UserName;
        public string UserName
        {
            get { return _UserName; }
            set { _UserName = value;  }
        }

        private string _Password;
        public string Password
        {
            get { return _Password; }
            set { _Password = value;  }
        }
    }


创建LoginVM(这是VM)

internal class LoginVM:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handle = PropertyChanged;
            if (handle != null)
            {
                handle(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        private LoginModel _LoginM;

		public LoginModel LoginM
        {
			get { 
				if(_LoginM == null)
					_LoginM = new LoginModel();
				return _LoginM; 
            }
			set { 
                _LoginM = value;
                RaisePropertyChanged("LoginM");
            }
		}
	}


主函数(这是V)

public partial class MainWindow : Window
    {
        LoginVM loginVm;
        public MainWindow()
        {
            InitializeComponent();
            loginVm = new LoginVM();
			
			//这行代码,就是将绑定的loginVm中,所以在xmal中binding 后面直接是LoginVM里的成员
            this.DataContext = loginVm;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

            if (loginVm.LoginM.UserName == "wpf" && loginVm.LoginM.Password == "666")
            {
                //弹出新的界面
                Index index = new Index();
                index.Show();

                //隐藏当前界面
                this.Hide();
            }
            else
            {
                //弹出一个警告框
                MessageBox.Show("输入的用户名或密码不正确");

                loginVm.LoginM.UserName = "";
                loginVm.LoginM.Password = "";

                //只有这里的代码不能在v上改变
                //此时的m是空,但是vm不是,所以重新将m的值赋予给vm
                loginVm.LoginM = loginVm.LoginM;
            }
        }
    }


xmal修改的地方

绑定发生变化
			<TextBlock Text="用户名" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"/>
            <TextBox Text="{Binding LoginM.UserName}"  Grid.Row="0" Grid.Column="1" Margin="2"/>
            
            <TextBlock Text="密码" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center"/>
            <TextBox Text="{Binding LoginM.Password}" Grid.Row="1" Grid.Column="1" Margin="2"/>


换一种写法
LoginModel没有变化
LoginVM将数据分别私有和暴露

		public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handle = PropertyChanged;
            if (handle != null)
            {
                handle(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        //方法二:直接暴露UserName
        private LoginModel _LoginM = new LoginModel();

        public string UserName { get { return _LoginM.UserName; } set { _LoginM.UserName = value;RaisePropertyChanged("UserName"); } }

        public string Password { get { return _LoginM.Password; } set { _LoginM.Password = value; RaisePropertyChanged("Password"); } }

V里面可以直接写,不同重新生成一次通知

private void Button_Click(object sender, RoutedEventArgs e)
        {

            if (loginVm.UserName == "wpf" && loginVm.Password == "666")
            {
                //弹出新的界面
                Index index = new Index();
                index.Show();

                //隐藏当前界面
                this.Hide();
            }
            else
            {
                //弹出一个警告框
                MessageBox.Show("输入的用户名或密码不正确");

                loginVm.UserName = "";
                loginVm.Password = "";
            }
        }

xmal里修改为最初的样子

			<TextBlock Text="用户名" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"/>
            <TextBox Text="{Binding UserName}"  Grid.Row="0" Grid.Column="1" Margin="2"/>
            
            <TextBlock Text="密码" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center"/>
            <TextBox Text="{Binding Password}" Grid.Row="1" Grid.Column="1" Margin="2"/>

MVVM命令
创建一个类(用来绑定命令),直接代码复制就可以

public class RelayCommond:ICommand
    {
        // 命令是否能够执行
        readonly Func<bool> _canExecute;

        //命令需要执行的方法
        readonly Action _execute;

        public RelayCommond(Action action,Func<bool> canExecute)
        {
            _execute = action;
            _canExecute = canExecute;
        }

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

        public void Execute(object parameter)
        {
            _execute();
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if(_canExecute != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }
            remove
            {
                if(_canExecute != null)
                {
                    CommandManager.RequerySuggested -= value;
                }
            }
        }
    }

M不发生改变

public class LoginModel
    {
        // 这里写法也固定,接收账号密码
        private string _UserName;
        public string UserName
        {
            get { return _UserName; }
            set { _UserName = value;  }
        }

        private string _Password;
        public string Password
        {
            get { return _Password; }
            set { _Password = value;  }
        }
    }

VM增加绑定需要的方法

internal class LoginVM : INotifyPropertyChanged
    {
        private MainWindow _main;
        public LoginVM(MainWindow main)
        {
            _main = main;
        }


        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handle = PropertyChanged;
            if (handle != null)
            {
                handle(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        //方法二:直接暴露UserName
        private LoginModel _LoginM = new LoginModel();

        public string UserName { get { return _LoginM.UserName; } set { _LoginM.UserName = value;RaisePropertyChanged("UserName"); } }

        public string Password { get { return _LoginM.Password; } set { _LoginM.Password = value; RaisePropertyChanged("Password"); } }

        //登录方法
        void LoginFunc()
        {
            if (UserName == "wpf" && Password == "666")
            {
                //弹出新的界面
                Index index = new Index();
                index.Show();

                //隐藏当前界面
                _main.Hide();
            }
            else
            {
                //弹出一个警告框
                MessageBox.Show("输入的用户名或密码不正确");

                UserName = "";
                Password = "";
            }
        }

        bool CanLoginExecute()
        {
            return true;
        }

        // 就是命令 等下绑定到登录按钮上
        public ICommand LoginAction
        {
            get
            {
                return new RelayCommond(LoginFunc, CanLoginExecute);
            }
        }
    }

V可以实现更简洁的代码

public MainWindow()
        {
            InitializeComponent();

            //将实例传过去,不然在vm里面不能使用hide隐藏
            this.DataContext = new LoginVM(this);
        }

xmal绑定案例

<Button Grid.Row="3" Grid.ColumnSpan="2" Content="登录" Command="{Binding LoginAction}"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值