如何将ComboBoxItem的IsEnabled属性绑定到Command的CanExecute方法的结果

时间:2010-02-23 18:05:50

标签: wpf xaml data-binding isenabled

我有一个自定义的SplitButton实现,其中包含一个ComboBox,其中包含几个绑定到命令的ComboBoxItem。我可以绑定到命令的Name和Text属性,但无法将ComboBoxItem的 IsEnabled 属性绑定到Command的 CanExecute 方法的结果,因为它是一个方法。是否有一些我不知道绑定到方法的语法,或者是否有一些技巧可以帮助我绑定到CanExecute。

顺便说一下,我已经考虑过使用自定义的ValueConverter,除了我意识到在重新评估CanExecute时我可能不会收到任何更新,因为它不是属性,因为我的命令不是业务对象。它在我看来,我可能必须为命令创建一个ViewModel,以便仅在我的自定义SplitButton控件中使用,但这对我来说似乎有些过分。

4 个答案:

答案 0 :(得分:1)

你可以在ItemContainerStyle(ComboBoxItem样式)中放一个按钮(如果你没有一个绑定到ICommand的controltemplate中),并将命令绑​​定到它 并添加一个Trigger来检查Button.IsEnabled并将该值设置为ComboBoxItem。所以这里我们使用Button作为CommandSource来从CanExeute获取IsEnabled。您可以将按钮的高度和宽度设置为零

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

答案 1 :(得分:1)

ViewModel的另一个解决方案。以下是我使用ViewModel解决问题的方法。请注意,漂亮的NotifyPropertyChanged方法是我的基本ViewModel类的一部分。

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

答案 2 :(得分:1)

我在MSDN论坛上找到了this discussion,其中Dr. WPF建议使用attached behavior来解决这个问题。他举了下面的例子,说明如何使用它。

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

虽然这个解决方案看起来很不错,但我还是没有时间去理解这种行为将如何实现以及涉及到什么。如果有人想详细说明请另外做,如果我有机会探索这个选项,我会更详细地修改这个答案。

答案 3 :(得分:0)

我在代码中解决此问题的方法是在ComboBox上为PreviewMouseDown事件添加事件处理程序。这是处理程序:

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

在我只需要在一个位置执行此操作的情况下,这对我很有用。如果我有很多像这样的页面,它可能会有点小调。

另外,虽然我遵循MVVM模式,但我不是纯粹主义者 - 我认为这是一个很好的实用解决方案,遵循MVVM的精神,如果不是字母。