界面参数的传递,界面参数是如何从前台传送到后台的。
param
参数是从界面传递到命令的。这个过程通常涉及以下几个步骤:
-
数据绑定:界面元素(如按钮)的
Command
属性绑定到视图模型中的RelayCommand
实例。同时,界面元素的CommandParameter
属性(如果有的话)可以绑定到视图模型中的某个属性或直接设置为一个静态值。这个CommandParameter
就是传递给RelayCommand
的param
参数。 -
命令触发:当用户与界面元素交互(例如点击按钮)时,会触发绑定的命令。WPF 框架会调用命令的
Execute
方法(如果命令可执行)或CanExecute
方法(以检查命令是否可执行)。 -
参数传递:在命令触发时,
CommandParameter
的值被传递给命令的Execute
和CanExecute
方法作为param
参数。 -
参数使用:在
RelayCommand
的 lambda 表达式中,param
被转换为ViewModel
类型(这里假设传递的参数实际上是ViewModel
类型的实例或可以安全地转换为ViewModel
类型)。然后,这个转换后的ViewModel
实例被传递给SaveUser
方法或IsUserSaveEnabled
方法。 -
属性访问:在
SaveUser
或IsUserSaveEnabled
方法中,就可以安全地访问ViewModel
实例的属性,如UserName
。由于这些方法接收的是已经转换为正确类型的ViewModel
实例,因此可以直接读取其属性。
一开始无法点击登录
然后点击账户历史自动填入
填入其他内容后再点击登录,账户历史会更新
ViewModel代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace Icommand练习
{
class ViewModel:INotifyPropertyChanged
{
private string _userName;
public string UserName
{
get { return _userName; }
set { _userName = value; OnPropertyChanged(nameof(UserName)); }
}
private string _email;
public string Email
{
get { return _email; }
set { _email = value; OnPropertyChanged(nameof(Email)); }
}
private string _tempUserName;
public string TempUserName
{
get { return _tempUserName; }
set { _tempUserName = value; }
}
private string _tempEmail;
public string TempEmail
{
get { return _tempEmail; }
set { _tempEmail = value; }
}
public ICommand SaveCommand { get; private set; }
public ViewModel()
{
SaveCommand = new RelayCommand(param => SaveUser((ViewModel)param), param => IsUserSaveEnabled((ViewModel)param));
Button2Command=new RelayCommand(param => Button2Click(), param=>true);
this.TempUserName = "网易";
this.TempEmail = "123456@163.com";
}
private void SaveUser(ViewModel user)
{
// 在这里实现保存用户的逻辑,比如调用API或保存到数据库
// 这里只是简单打印用户信息
MessageBox.Show($"Saving user: UserName={user.UserName}, Email={user.Email}");
user.TempUserName = _userName;
user.TempEmail = _email;
}
private bool IsUserSaveEnabled(ViewModel viewModel)
{
if (viewModel == null)
{
// 如果 param 不是 ViewModel 类型或者为 null,则返回 false
return false;
}
// 现在可以安全地访问 viewModel.UserName
return !string.IsNullOrEmpty(viewModel.UserName);
}
public ICommand Button2Command { get; }
public void Button2Click()
{
UserName = TempUserName;
Email = TempEmail;
}
//固定
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
//public class RelayCommand : ICommand
//{
// private readonly Action<object> _execute;
// public event EventHandler CanExecuteChanged;
// public RelayCommand(Action<object> execute) => _execute = execute;
// public bool CanExecute(object parameter) => true; // 总是可执行(简化)
// public void Execute(object parameter) => _execute(parameter);
//}
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
// 可以在这里添加额外的逻辑来处理 CanExecuteChanged 事件的触发,但上面的实现已经足够用于大多数场景。
}
}
XAMl代码:
<Window x:Class="Icommand练习.MainWindow"
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"
xmlns:local="clr-namespace:Icommand练习"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="登录" Command="{Binding SaveCommand}" CommandParameter="{Binding}" />
<Button Command="{Binding Button2Command}" Content="账户历史"/>
</StackPanel>
</Window>