【问题标题】:[UWP/MVVM]Enable/Disable Button in RadDataGrid Data Template Column that have commands bound to them upon conditions[UWP/MVVM]RadDataGrid 数据模板列中的启用/禁用按钮,该按钮根据条件绑定了命令
【发布时间】:2019-02-21 20:36:10
【问题描述】:

我设置了一个 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);
    }
}

xml

<DataTemplate>
                                <Button Command="{Binding Source={StaticResource VM},
                                Path=Command}" CommandParameter="{Binding}" >
                                    <SymbolIcon Symbol="Edit" Foreground="AliceBlue" />
                                </Button>
</DataTemplate>

可以在虚拟机中执行

 private bool CanGetDetails(object obj)
    {
        return true;
    }

【问题讨论】:

    标签: c# .net xaml uwp


    【解决方案1】:

    您始终可以在自定义命令的 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 或标准方法来填充这些参数。

    示例视图模型:

    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>
    

    【讨论】:

    • 谢谢,这个对我很有效。之前设置自定义命令的方式不适合我们做事的方式。您能否详细说明命令以及为什么每个 CanExecute 有两个?
    • 嗨!我清理了代码并添加了有关自定义命令的更多详细信息。
    • 谢谢。如果不允许这样做,我很抱歉,但你能否支持我的问题,以便我可以提高我的声誉。非常感谢。
    • 这可以通过一个按钮的多个条件来完成吗?
    • 是的,如果您将所有条件都放在 CanEdit 函数中,则无论是否满足条件,都返回布尔结果。
    【解决方案2】:

    我认为你可以从 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();
        }
    

    然后,无论您在命令中作为谓词放置什么,在谓词的布尔设置器中执行:

    SomeCustomCommand.RaiseCanExecuteChanged()
    

    希望我能帮上忙。

    【讨论】:

    • 我希望我能给你投票,因为我确信它有效,但下面的答案对我有用。
    猜你喜欢
    • 1970-01-01
    • 2021-01-06
    • 2019-02-27
    • 2017-10-30
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 2021-12-13
    相关资源
    最近更新 更多