WinUI 3中如何通过按钮一次性传递多个控件的值至RelayCommand
嘿,我来帮你解决这个WinUI 3里的小问题!你想通过按钮一次性把两个TextBox的值传给RelayCommand,其实有几个实用的方案,我给你挨个说清楚:
1. MVVM属性绑定(最推荐,符合规范)
其实在MVVM模式下,我们完全不用纠结CommandParameter的单参数限制——因为根本不需要传参数!我们可以直接把TextBox的文本和ViewModel里的属性做双向绑定,按钮的Command执行时直接取ViewModel里的属性值就行。
第一步:修改XAML,绑定ViewModel属性
把两个TextBox的Text属性和你ViewModel里的FirstName、LastName做双向绑定:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal"> <TextBlock Text="First Name"/> <TextBox Header="First Name" Text="{x:Bind ViewModel.FirstName, Mode=TwoWay}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Last Name"/> <TextBox Header="Last Name" Text="{x:Bind ViewModel.LastName, Mode=TwoWay}" /> </StackPanel> <Button Content="Save" Command="{x:Bind ViewModel.SaveCommand}" /> </StackPanel>
第二步:在ViewModel里实现属性和Command
假设你用的是CommunityToolkit.Mvvm(WinUI里常用的MVVM工具包),ViewModel可以这么写:
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; public class YourViewModel : ObservableObject { // 定义和TextBox绑定的FirstName属性 private string _firstName; public string FirstName { get => _firstName; set => SetProperty(ref _firstName, value); } // 定义和TextBox绑定的LastName属性 private string _lastName; public string LastName { get => _lastName; set => SetProperty(ref _lastName, value); } // 定义SaveCommand public IRelayCommand SaveCommand { get; } public YourViewModel() { SaveCommand = new RelayCommand(ExecuteSave); } // Command的执行方法,直接取属性值 private void ExecuteSave() { string firstName = FirstName; string lastName = LastName; // 这里直接用这两个值执行你的SQLite插入操作就行啦 } }
这种方式完全符合MVVM的“UI和业务逻辑分离”思想,代码也更干净好维护,是最推荐的做法。
2. 用CommandParameter传递打包对象
如果你暂时不想改绑定逻辑,也可以把两个TextBox的值打包成一个对象,通过CommandParameter传过去。
方案A:传递匿名对象(快速实现)
直接在XAML里用{x:Bind}创建匿名对象,把两个文本框的值塞进去:
<StackPanel x:Name="RootPanel" Orientation="Horizontal" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal"> <TextBlock Text="First Name"/> <TextBox x:Name="firstNameBox" Header="First Name" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Last Name"/> <TextBox x:Name="lastNameBox" Header="Last Name" /> </StackPanel> <Button Content="Save" Command="{x:Bind ViewModel.SaveCommand}" CommandParameter="{x:Bind new { FirstName = firstNameBox.Text, LastName = lastNameBox.Text }, Mode=OneWay}" /> </StackPanel>
然后ViewModel里的RelayCommand要接收object类型参数,用dynamic来解析:
public IRelayCommand<object> SaveCommand { get; } public YourViewModel() { SaveCommand = new RelayCommand<object>(ExecuteSave); } private void ExecuteSave(object parameter) { if (parameter is dynamic param) { string firstName = param.FirstName; string lastName = param.LastName; // 执行SQLite操作 } }
方案B:传递强类型对象(更安全)
为了避免dynamic的类型不安全问题,我们可以先定义一个简单的类来存这两个值:
public class PersonInfo { public string FirstName { get; set; } public string LastName { get; set; } }
然后XAML里的CommandParameter改成创建这个类的实例:
CommandParameter="{x:Bind new PersonInfo { FirstName = firstNameBox.Text, LastName = lastNameBox.Text }, Mode=OneWay}"
ViewModel里的RelayCommand就可以直接接收PersonInfo类型:
public IRelayCommand<PersonInfo> SaveCommand { get; } public YourViewModel() { SaveCommand = new RelayCommand<PersonInfo>(ExecuteSave); } private void ExecuteSave(PersonInfo info) { if (info != null) { string firstName = info.FirstName; string lastName = info.LastName; // 执行SQLite操作 } }
3. 后台代码直接获取(适合简单非MVVM场景)
如果你没在用MVVM,只是想快速实现功能,那直接给按钮加Click事件,在后台代码里直接拿两个TextBox的文本就行:
<Button Content="Save" Click="SaveButton_Click" />
后台代码:
private void SaveButton_Click(object sender, RoutedEventArgs e) { string firstName = firstNameBox.Text; string lastName = lastNameBox.Text; // 执行你的SQLite插入操作 }
不过这种方式就和RelayCommand无关了,适合小型简单的页面,大型项目还是推荐用MVVM的方式。
总的来说,最推荐第一种MVVM属性绑定的方案,既规范又好维护;如果是临时需求,第二种传递打包对象的方式也能快速解决问题。
备注:内容来源于stack exchange,提问作者Nuvolari

