[UWP/MVVM]Enable/Disable Button in RadDataGrid Data Template Column that have commands bound to them upon conditions

后端 未结 2 517
孤城傲影
孤城傲影 2020-12-21 22:27

I have set a bool property and have bound it to the IsEnabled in the xaml but the ICommand CanExecute method overrides the IsEnabled in xaml, so my bool property is ineffect

相关标签:
2条回答
  • 2020-12-21 22:58

    You can always do your conditional statement within the CanExecute function of your custom command, no need for you to bind IsEnabled property with your button that is bound to a command. Here's a sample implementation, hope this helps.

    Custom Command:

    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;
    }
    

    As you can see here, I created an object that implements the ICommand interface, this custom command accepts a generic type parameter which is used to evaluate a condition (CanExecute: this tells whether to enable or disable a command (in UI, the button), normally use to check for permissions, and other certain conditions) this parameter is also used to execute the action (Execute: the actual logic/action to be performed), The command contructor accepts delegate parameters that contain signatures for these 2 methods, the caller may choose lambda or standard methods to fillup these parameters.

    Sample 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>
    

    0 讨论(0)
  • 2020-12-21 23:13

    I think you can pick a lot of code from the RelayCommand of MVVMLight. Try to change your event to

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (canExecute != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }
    
            remove
            {
                if (canExecute != null)
                {
                    CommandManager.RequerySuggested -= value;
                }
            }
        }
    

    and add also a function

        public void RaiseCanExecuteChanged()
        {
            CommandManager.InvalidateRequerySuggested();
        }
    

    Then, whatever you put as your Predicate on the command, at the Predicate's boolean setter do:

    SomeCustomCommand.RaiseCanExecuteChanged()
    

    Hope I helped.

    0 讨论(0)
提交回复
热议问题