4

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

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

4

4 回答 4

1

您可以在 ItemContainerStyle(ComboBoxItem 样式)中放置一个按钮(如果在绑定到 ICommand 的控件模板中没有按钮)并将命令绑​​定到它并添加一个触发器来检查 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>
于 2010-02-23T18:29:18.610 回答
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);
    }
}
于 2010-02-23T21:07:44.387 回答
1

我在 MSDN 论坛上发现了这个讨论,其中WPF 博士建议使用附加行为来解决这个确切的问题。他在下面给出了如何使用它的例子。

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

尽管这个解决方案看起来很不错,但我还没有花时间来准确地了解这种行为将如何实现以及涉及到什么。如果有人想详细说明,请不要这样做,如果我有机会探索这个选项,我会用更多细节修改这个答案。

于 2010-02-24T13:37:31.220 回答
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 的精神,如果不是字母的话。

于 2011-05-27T15:12:45.967 回答