我设置了bool属性并将其绑定到xaml中的IsEnabled,但ICommand CanExecute方法覆盖了xaml中的IsEnabled,因此我的bool属性无效。
当我在视图模型中定义CanExecute方法中的条件时,它会禁用方法所绑定的所有按钮,或者启用所有这些按钮。
它是一个网格,每行显示3个不同的按钮,每个按钮转到一个新的xaml屏幕。如果按钮所在的行上没有特定条件的数据,则需要禁用该按钮。
我如何设置此项以便按钮在某种情况下被禁用?
自定义命令:
public class CustomCommand : ICommand
{
private Action<object> execute;
private Predicate<object> canExecute;
public CustomCommand(Action<object> execute, Predicate<object> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
}
remove
{
}
}
public bool CanExecute(object parameter)
{
//throw new NotImplementedException();
bool b = canExecute == null ? true : canExecute(parameter);
return b;
}
public void Execute(object parameter)
{
execute(parameter);
}
}
XAML
<DataTemplate>
<Button Command="{Binding Source={StaticResource VM},
Path=Command}" CommandParameter="{Binding}" >
<SymbolIcon Symbol="Edit" Foreground="AliceBlue" />
</Button>
</DataTemplate>
CanExecute在VM中
private bool CanGetDetails(object obj)
{
return true;
}
您始终可以在自定义命令的CanExecute函数中执行条件语句,无需将IsEnabled属性与绑定到命令的按钮绑定。这是一个示例实现,希望这会有所帮助。
自定义命令:
public class CustomCommand<T> : ICommand
{
private readonly Action<T> _action;
private readonly Predicate<T> _canExecute;
public CustomCommand(Action<T> action, Predicate<T> canExecute)
{
_action = action;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute((T)parameter);
}
public void Execute(object parameter)
{
_action((T)parameter);
}
public event EventHandler CanExecuteChanged;
}
正如您在此处所看到的,我创建了一个实现ICommand接口的对象,此自定义命令接受用于评估条件的泛型类型参数(CanExecute:它告诉是否启用或禁用命令(在UI中,按钮) ,通常用于检查权限,以及其他某些条件)此参数也用于执行操作(执行:要执行的实际逻辑/操作),命令构造函数接受包含这两种方法的签名的委托参数,调用者可以选择lambda或标准方法来填充这些参数。
示例ViewModel:
public class ViewModel1: INotifyPropertyChanged
{
public ViewModel1()
{
// Test Data.
Items = new ObservableCollection<ItemViewModel>
{
new ItemViewModel{ Code = "001", Description = "Paint" },
new ItemViewModel{ Code = "002", Description = "Brush" },
new ItemViewModel{ Code = "003", Description = "" }
};
EditCommand = new CustomCommand<ItemViewModel>(Edit, CanEdit);
}
public CustomCommand<ItemViewModel> EditCommand { get; }
private bool CanEdit(ItemViewModel item)
{
return item?.Description != string.Empty;
}
private void Edit(ItemViewModel item)
{
Debug.WriteLine("Selected Item: {0} - {1}", item.Code, item.Description);
}
private ObservableCollection<ItemViewModel> _items { get; set; }
public ObservableCollection<ItemViewModel> Items
{
get => _items;
set
{
_items = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML:
<Page x:Name="root"
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vms="using:App1.ViewModels"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
d:DesignHeight="450" d:DesignWidth="800">
<Page.DataContext>
<vms:ViewModel1 x:Name="Model"/>
</Page.DataContext>
<Grid>
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0 0 0 15">
<TextBlock Text="{Binding Code}" />
<TextBlock Text="{Binding Description}" />
<Button Content="Edit" Command="{Binding DataContext.EditCommand, ElementName=root}" CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Page>
我想你可以从MVVMLight的RelayCommand中选择很多代码。尝试将您的活动更改为
public event EventHandler CanExecuteChanged
{
add
{
if (canExecute != null)
{
CommandManager.RequerySuggested += value;
}
}
remove
{
if (canExecute != null)
{
CommandManager.RequerySuggested -= value;
}
}
}
并添加一个功能
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
然后,无论你把什么作为你的Predicate放在命令上,在Predicate的布尔设置器上做:
SomeCustomCommand.RaiseCanExecuteChanged()
希望我帮忙。