How to bind a ComboBoxItem's IsEnabled property to the result of a Command's CanExecute method

自作多情 提交于 2019-12-10 10:08:53

问题


I've a custom SplitButton implementation in which contains a ComboBox with several ComboBoxItems bound to commands. I can bind to the Name, and Text properties of the command just fine but have no way of binding the ComboBoxItem's IsEnabled property to the result of a Command's CanExecute method because it is a method. Is there some syntax that I'm unaware of for binding to methods or is there some trickery that will help me to bind to CanExecute.

By the way, I've thought about using a custom ValueConverter except for that I realized that I probably wouldn't receive any updates when CanExecute is re-evaluated since it is not a property and since my commands are not business objects. It's looking to me that I might have to create a ViewModel for a command at this point to use only within my custom SplitButton control but that seems a little overboard to me.


回答1:


You can put a button(if you dont have one in the controltemplate bound to the ICommand) inside ItemContainerStyle(ComboBoxItem style) and Bind the command to it And add a Trigger to check the Button.IsEnabled and set that value to the ComboBoxItem. So here we used Button as a CommandSource just to get the IsEnabled from CanExeute. You can set the button's height and width to zero

 <ControlTemplate....>
   <Grid ...
       <Button x:Name="dummyButton" Command="{Binding YourCommand}" ....
           ......
   </Grid>

   <ControlTemplate.Triggers>
      <Trigger SourceName="dummyButton" Property="IsEnabled" Value="False">
        <Setter Property="IsEnabled" Value="False"/>
      </Trigger>
   </ControlTemplate.Triggers>



回答2:


Another solution by ViewModel. Below is how I used a ViewModel to solve my problem. And please note that the nifty NotifyPropertyChanged method is part of my base ViewModel class.

public class RoutedUICommandViewModel : ViewModel
{
    private RoutedUICommand _command;
    private IInputElement _target;

    public string Name { get { return _command.Name; } }

    public string Text { get { return _command.Text; } }

    public bool CanExecute
    {
        get
        {
            return _command.CanExecute(null, _target);
        }
    }

    public RoutedUICommand Command { get { return _command; } }

    public RoutedUICommandViewModel(ReportCommand command, IInputElement target)
    {
        _command = command;
        _target = target;
        _command.CanExecuteChanged += _command_CanExecuteChanged;
    }

    private void _command_CanExecuteChanged(object sender, EventArgs e)
    {
        base.NotifyPropertyChanged(() => this.CanExecute);
    }
}



回答3:


I found this discussion on MSDN forums where Dr. WPF had recommended the use of an attached behavior to solve this exact problem. He gave the example below of how it would be used.

<Grid behaviors:CommandBehaviors.EnablingCommand="{x:Static commands:testcommand.test}">  
  . . .  
</Grid> 

Although this solution seems pretty nice I haven't been able to devote the time to understand exactly how this type of behavior would be implemented and what is involved. If anybody would like to elaborate please do otherwise I'll amend this answer with more details if I get the chance to explore this option.




回答4:


The way I solved this problem in my code was to add an event handler on the ComboBox for the PreviewMouseDown event. Here's the handler:

private void comboBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            ViewModel vm = this.DataContext as ViewModel;

            if (vm != null)
            {
                if (!vm.CanChangeSelection())
                {
                    e.Handled = true;
                    vm.RespondToFailedAttemptChangeUnits();
                }
            }
        }

This works great for me in the case that I only need to do this in one location. It might get a little tedius if I had many pages like this.

Also, though I follow the MVVM pattern, I'm not a purist - I consider this to be a good practical solution that follows the spirit of MVVM, if not the letter.



来源:https://stackoverflow.com/questions/2320553/how-to-bind-a-comboboxitems-isenabled-property-to-the-result-of-a-commands-can

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!