我的窗口上有一个复选框控件。我想执行一个命令来调用关联视图模型中的方法。我还需要复选框的值。我似乎找不到将命令与复选框关联起来的方法。有人做过吗?
<CheckBox Content="CheckBox"
Command="{Binding YourCommand}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}" />
如果你使用MVVM,你可以使用这样的事件触发器:
<CheckBox IsChecked="{Binding ServiceOrderItemTask.IsCompleted, Mode=TwoWay}" Content="{Binding ServiceOption.Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding DataContext.IsCompletedCheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type t:RadGridView}}}" CommandParameter="{Binding}"/>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<i:InvokeCommandAction Command="{Binding DataContext.IsCompletedUncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type t:RadGridView}}}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
这将满足您的要求 -
<CheckBox CommandParameter="{Binding}"
Command="{Binding DataContext.YourCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}}"
Content="{Binding Path=Name}">
System.Windows.Interactivity
添加到您的项目参考中。 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
添加到您的 XAML 命名空间。<CheckBox IsChecked="{Binding SomeBoolProperty, Mode=OneWay}" Content="Check Meee!">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding MyOnCheckedCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<i:InvokeCommandAction Command="{Binding MyOnUncheckedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
我在 ViewModel 上实现
INotifyPropertyChanged
,如下所示:
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
我的 ViewModel 的
SomeBoolProperty
看起来像这样:
private bool _SomeBoolProperty = false;
public bool SomeBoolProperty {
get => _SomeBoolProperty;
set {
_SomeBoolProperty = value;
OnPropertyChanged(nameof(SomeBoolProperty));
}
}
我使用 RelayCommand 作为我的命令实现 https://stackoverflow.com/a/22286816/336753。
我的 ViewModel 上的命令如下所示:
public ICommand MyOnCheckedCommand { get; } = new RelayCommand(o => {
// Do something here.
SomeBoolProperty = true;
});
public ICommand MyOnUncheckedCommand { get; } = new RelayCommand(o => {
// Do something else here.
SomeBoolProperty = false;
});
我遇到了这个问题,试图找到一种方法来“重用”我的 ViewModel 上已有的两个命令。一个在选中时调用,一个在未选中时调用。我也在一些按钮上使用它们,所以不想添加额外的参数化命令。人们在这里询问有关 ViewModel 实现的问题,因此添加此答案来完成 Igor_S 的答案。希望有帮助。
该示例是一个工作代码摘录,它只是为了帮助理解各个方面。它是一个图钉,可以是活动的也可以是非活动的,并且它使用 DelegateCommand。您也可以使用 RelayCommand 或任何其他类似的类来完成相同的工作。
命令:
using System.Windows.Input;
namespace HQ.Wpf.Util.Command
{
public class StandardCommand
{
public static RoutedUICommand PinPropertyGrid = new RoutedUICommand("Pin property grid", "PinPropertyGrid", typeof(StandardCommand));
Xaml:
<CheckBox HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="2,0,3,0"
Command="{Binding CommandPinPropertyGrid}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}">
<CheckBox.Template>
<ControlTemplate TargetType="{x:Type CheckBox}">
<Grid>
<Image x:Name="ImagePushpin" Width="16" Height="16" Source="pack://application:,,,/WpfUtil;component/Images/PushpinUnpinned16x16.png" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="ImagePushpin" Property="Source" Value="pack://application:,,,/WpfUtil;component/Images/PushpinPinned16x16.png" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</CheckBox.Template>
</CheckBox>
型号:
public MainWindowViewModel()
{
CommandPinPropertyGrid = new DelegateCommand<bool>(PinPropertyGrid);
...
// ******************************************************************
public DelegateCommand<bool> CommandPinPropertyGrid { get; private set; }
public void PinPropertyGrid(bool pinned)
{
this.IsPropertyGridPinned = pinned;
}
委托命令:
using System;
using System.Windows.Input;
namespace HQ.Wpf.Util.Command
{
/// <summary>
/// Represents a command that forwards the <c>Execute</c> and <c>CanExecute</c> calls to specified delegates.
/// </summary>
public class DelegateCommand<T> : ICommand
{
private readonly Action<T> _executeCallback;
private readonly Predicate<T> _canExecuteCallback;
/////////////////////////////////////////////////////////////////////////////////////////////////////
// OBJECT
/////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Initializes a new instance of the <see cref="DelegateCommand<T>"/> class.
/// </summary>
/// <param name="executeCallback">The execute callback delegate.</param>
public DelegateCommand(Action<T> executeCallback)
: this(executeCallback, null)
{
// No-op
}
/// <summary>
/// Initializes a new instance of the <see cref="DelegateCommand<T>"/> class.
/// </summary>
/// <param name="executeCallback">The execute callback delegate.</param>
/// <param name="canExecuteCallback">The can execute callback delegate.</param>
public DelegateCommand(Action<T> executeCallback, Predicate<T> canExecuteCallback)
{
if (executeCallback == null)
throw new ArgumentNullException("executeCallback");
this._executeCallback = executeCallback;
this._canExecuteCallback = canExecuteCallback;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// INTERFACE IMPLEMENTATION
/////////////////////////////////////////////////////////////////////////////////////////////////////
#region ICommand Members
/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null"/>.</param>
/// <returns>
/// <c>true</c> if this command can be executed; otherwise, <c>false</c>.
/// </returns>
public bool CanExecute(object parameter)
{
return (this._canExecuteCallback == null) ? true : this._canExecuteCallback((T)parameter);
}
/// <summary>
/// Occurs when changes occur that affect whether or not the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged
{
add
{
if (this._canExecuteCallback != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (this._canExecuteCallback != null)
CommandManager.RequerySuggested -= value;
}
}
/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null"/>.</param>
public void Execute(object parameter)
{
this._executeCallback((T)parameter);
}
#endregion // ICommand Members
}
}
这是我根据 Microsoft 文档和其他 SO 问题尝试过的东西:
IsChecked
属性绑定到视图模型中的 ObservableProperty
。与单独问题的
这个答案和这个答案类似,我最终使用了 .NET MAUI 社区工具包中的EventToCommandBehavior行为。我不知道这是否适用于 WPF,抱歉。 这是我针对此示例的简化代码。
MainPage.xaml
:
<ContentPage
x:Class="MyProject.Views.MainPage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:viewmodel="clr-namespace:MyProject.ViewModels"
x:DataType="viewmodel:MainPageViewModel">
<CheckBox x:Name="WholeNameCheckbox"
IsChecked="{Binding IsExactMatch}"
HorizontalOptions="Center">
<CheckBox.Behaviors>
<toolkit:EventToCommandBehavior
EventName="CheckedChanged"
Command="{Binding ExactMatchCheckedCommand}"
CommandParameter="{Binding IsChecked, Source={x:Reference WholeNameCheckbox}}"/>
</CheckBox.Behaviors>
</CheckBox>
</ContentPage>
MainPage.xaml.cs
:
namespace MyProject.Views;
public partial class MainPage : ContentPage
{
public MainPage(MainPageViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel;
}
}
MainPageViewModel.cs
:
using MyProject.Services;
using MvvmHelpers; // For [RelayCommand]
namespace MyProject.ViewModels;
public partial class MainPageViewModel : BaseViewModel
{
// ObservableProperty gives the variable a public property and
// all the NotifyChanges interfaces and gives the properties
// OnPropertyChanged() methods.
[ObservableProperty]
bool _returnsPartialMatch;
[ObservableProperty]
bool _returnsPartialMatchWithSpace;
[ObservableProperty]
public bool _isExactMatch;
[RelayCommand]
async Task ExactMatchCheckedAsync(bool isChecked_p)
{
// Offload processing to thread pool.
await Task.Run(() =>
{
// Do stuff in your view model using your properties or whatever
}
}
}
按预期工作 - 当选中“精确匹配”复选框时,
IsExactMatch
属性为
True
,无论哪种方式,当选中状态更改时,它都会调用视图模型中的异步方法并将其 IsChecked 属性值传递给该方法。由于此命令是在 IsExactMatch 属性更改后调用的,因此该值更改或需要验证它的时间并不奇怪。CheckBox box = e.OriginalSource as CheckBox;
if(box.IsChecked.Value)
DoThis();
else
DoAnotherMethod();
“e”是命令中的 ExecutedRoulatedEventArgs 参数。您需要 box.IsChecked.Value,因为 box.IsChecked 来自类型 bool?.