在主窗口中使用带有用户控件的RoutedCommand

时间:2017-02-18 15:17:38

标签: c# wpf user-controls routed-commands

我正在尝试了解路由命令的工作原理,但我遇到了问题。我创建了一个带有Button和ItemControl的主窗口,其中UserControls作为其Item模板。

<Window>
<Grid>
<ItemsControl
            ItemsSource="{Binding CollectionOfUsers}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <uc:UserUserControl
                        Name="{Binding PersonName}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
<Button
      Command="{x:Static helpers:RoutedCommands.SendChangesCommand}"
      Content="SAVE"/>
</Grid>
</Window>

如果单击主窗口中的按钮,我想从ItemsControl中的每个UserControl运行一些方法。

我在静态类中创建了RoutedCommand:

public static class RoutedCommands
{
    public static readonly RoutedCommand SendChangesCommand = new RoutedCommand(); 
}

将UserControl绑定到RoutedCommand。

<UserControl.CommandBindings>
    <CommandBinding Command="{x:Static helpers:RoutedCommands.SendChangesCommand}"
                    Executed="CommandBinding_Executed"/>

使用代码隐藏方法:

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
      // Do something
}

当我点击按钮时,它会在每个User Control对象上触发方法,但遗憾的是这段代码不起作用 - 按钮被禁用。我错过了什么?

2 个答案:

答案 0 :(得分:0)

您可以/应该发送ItemsControl的public static class RoutedCommands { public static readonly RoutedCommand SendChangesCommand = new RoutedCommand(); public static void CanExecuteSendChangesCommand(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; } public static void ExecutedSendChangesCommand(object sender, ExecutedRoutedEventArgs e) { // Use e.Parameter; } } 作为Button的CommandParameter,并使用这些项目(模型)执行您喜欢的任何操作。使用正确的Bindings,您可以在UserControls(View)中查看结果。这是一个例子:

假设这是RoutedCommands:

CommandBindings

该命令将添加到应用程序中的 public MainWindow() { InitializeComponent(); CommandBindings.Add(new CommandBinding(RoutedCommands.SendChangesCommand, RoutedCommands.ExecutedSendChangesCommand,RoutedCommands.CanExecuteSendChangesCommand)); } ,例如:

<DockPanel>
    <Button DockPanel.Dock="Top" Content="Click Me" 
            Command="{x:Static local:RoutedCommands.SendChangesCommand}"
            CommandParameter="{Binding ElementName=ic, Path=ItemsSource}"/>
    <ItemsControl Name="ic" ItemsSource="{Binding CollectionOfUsers}">
        //...
    </ItemsControl>
</DockPanel>

您可以使用以下内容绑定Command参数:

{{1}}

答案 1 :(得分:0)

  

当我点击按钮时,它会在每个User Control对象上触发方法,但遗憾的是这段代码不起作用 - 按钮被禁用。我错过了什么?

A RoutedCommand从目标元素搜索可视树,即在这种情况下调用命令的元素Button, 以及在CommandBinding集合中具有匹配的CommandBindings对象的元素,然后为此特定Execute执行CommandBinding委托。

这里的问题是UserControl中的ItemsControl元素不是Button的可视父元素,因此永远不会调用该命令。

如果您将CommandBinding移至父Grid,则会启用Button

<Grid>
    <Grid.CommandBindings>
        <CommandBinding Command="{x:Static local:RoutedCommands.SendChangesCommand}"
            Executed="CommandBinding_Executed"/>
    </Grid.CommandBindings>
    <ItemsControl
    ...

如果您真的想在点击UserControls时对Button执行某些操作,则使用RoutedCommand不是这样做的方法。

相反,您应该查看MVVM design pattern以及如何实现自定义ICommand或使用任何MVVM库中的通用实现。这是另一个故事,但请参阅以下博客文章以获得简要介绍:https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/

MVVM是 推荐的设计模式,用于构建基于XAML的应用程序,所有认真的WPF开发人员都应该学习它。