【问题标题】:How to use Commands to react to a ListBox如何使用命令对 ListBox 做出反应
【发布时间】:2017-11-28 14:25:09
【问题描述】:

我正在尝试学习命令并设置了一个简单的 wpf 项目来使用自定义命令。我有一个列表框和一个窗口上的按钮。当 ListBox 有焦点并选择了一个 Item 时,我希望 Button 启用,否则应该禁用它。

我在一个单独的 CustomCommands 类中定义了一个 CustomCommand:

Public Shared ReceivedFocus As New RoutedCommand

在我的窗口中我设置如下:

<CommandBinding
    Command="{x:Static local:CustomCommands.ReceivedFocus}"
    CanExecute="CanActivate"
    Executed="ChangeSelection">
</CommandBinding>

并使用 ListBox 的命令如下:

<ListBox
    x:Name="lstInactive">
    <i:Interaction.Triggers>
        <i:EventTrigger
            EventName="GotFocus">
            <i:InvokeCommandAction
                Command="{x:Static local:CustomCommands.ReceivedFocus}"
            </i:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>

最后,CanActivate 例程是:

Private Sub CanActivate(sender As Object, e As CanExecuteRoutedEventArgs)
        If lstInactive.SelectedIndex >= 0 Then
            e.CanExecute = True
        Else
            e.CanExecute = False
        End If
End Sub

这不起作用。主要问题是我不明白如何将 CanExecute 值与 Button 相关联。我是否应该忽略 CanActivate 例程中的 CanExecute 值,而只设置 Button 的 Enabled 属性?如果是,CanExecuteRoutedEventArgs 的 CanExecute 参数的值是多少?

第二个问题是 GotFocus 事件在我第二次选择 ListBox 中的项目之前不会触发。

也许我根本没有掌握指挥,这不是正确的方法。这个小项目本身并不重要,它的目的是在我开始在“真实”项目中使用命令之前,确保我在阅读了大量有关命令的文章后理解命令。可悲的是,现阶段很明显我没有。

【问题讨论】:

  • 如果你想要一个Button 来表示命令的状态,你确实需要将Button.Command 属性绑定到该命令。我建议您在视图模型中创建命令,而不是使用静态引用和CommandBinding。这样做,您将拥有一个定义明确的概念,将逻辑与表示分开。将ListBox.SelectedItem 绑定到视图模型的属性,并在视图模型中决定该命令是否可以执行。
  • 投反对票的依据是什么?

标签: wpf listbox routed-commands


【解决方案1】:

这不起作用。主要问题是我不明白如何将 CanExecute 值与 Button 相关联。

将其Command 属性绑定到同一命令:

<Button Content="Button" Command="{x:Static local:CustomCommands.ReceivedFocus}" />

然后应根据您在CanActivate 事件处理程序中设置CanExecute 属性的值启用或禁用Button

您可能还想收听SelectionChanged 事件。这按预期工作:

<StackPanel>
    <StackPanel.CommandBindings>
        <CommandBinding
                Command="{x:Static local:CustomCommands.ReceivedFocus}"
                CanExecute="CanActivate"
                Executed="ChangeSelection">
        </CommandBinding>
    </StackPanel.CommandBindings>

    <ListBox x:Name="lstInactive">
        <ListBoxItem>first</ListBoxItem>
        <ListBoxItem>second</ListBoxItem>
        <ListBoxItem>third</ListBoxItem>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <i:InvokeCommandAction Command="{x:Static local:CustomCommands.ReceivedFocus}">
                </i:InvokeCommandAction>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </ListBox>

    <Button Content="Button" Command="{x:Static local:CustomCommands.ReceivedFocus}" />
</StackPanel>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void CanActivate(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = lstInactive.SelectedIndex >= 0;
    }

    private void ChangeSelection(object sender, ExecutedRoutedEventArgs e)
    {

    }
}

【讨论】:

  • @mm 这不起作用,因为它强制按钮执行与选择列表框中的项目相同的命令。在我的应用程序中,唯一要采取的操作是在窗口上设置几个按钮的 e.CanExecute。
  • 我确实从您的回答中得到了帮助,并相应地修改了我的代码。我将按钮的命令设置为不同的例程,并设置 ListBox GotFocus 和选择更改命令以设置 e.CanExecute=True。但是,由于某种原因,这仍然没有将 IsEnabled 按钮属性更改为 True。如果有帮助,我可以发布修改后的代码。
  • 顺便说一句,我知道需要“观察”ListBox 的 SelectionChanged 事件。我只是想让你知道我并非完全无能;它就是这样出现的。
  • IsEnabled 属性不应更改。绑定到命令时不使用它,即要么使用 IsEnabled 属性启用按钮使用命令的 CanExecute 方法。
猜你喜欢
  • 2017-06-11
  • 2021-02-06
  • 2020-04-11
  • 2020-10-29
  • 1970-01-01
  • 2021-02-18
  • 2022-07-28
  • 2021-04-30
  • 2021-06-23
相关资源
最近更新 更多