RoutedCommands, связанные подэлементами, никогда не запускаются
Я пытаюсь разобраться с RoutedCommands в WPF. Мне нравится, как они уменьшают связь между различными элементами пользовательского интерфейса и моделями, но я не могу заставить привязки работать для пользовательских элементов управления, которые являются дочерними элементами для окна. Я полагаю, что это будет простой задачей для любого из вас, волшебников WPF!:-)
Вот пример кода, который можно попробовать:
Направленная команда:
using System.Windows.Input;
namespace Wpf.RoutedCommands
{
public static class Commands
{
public static readonly RoutedCommand SayHi = new RoutedCommand();
}
}
Главное окно XAML:
<Window x:Class="Wpf.RoutedCommands.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Wpf.RoutedCommands"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<!-- uncommenting the below makes it work but introduces coupling -->
<!--<Window.CommandBindings>
<CommandBinding Command="{x:Static local:Commands.SayHi}" Executed="cmdSayHi" CanExecute="cmdCanSayHi"></CommandBinding>
</Window.CommandBindings>-->
<DockPanel LastChildFill="True">
<Button DockPanel.Dock="Bottom" Content="Say Hi!" Command="{x:Static local:Commands.SayHi}" />
<local:Greeter x:Name="Greeter" />
</DockPanel>
Код главного окна:
using System.Windows.Input;
namespace Wpf.RoutedCommands
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
// these two will be used if you uncomment the command bindings in XAML
private void cmdCanSayHi(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = true;
private void cmdSayHi(object sender, ExecutedRoutedEventArgs e) => Greeter.SayHi();
}
}
Пользовательский контроль ("Greeter") XAML:
<UserControl x:Class="Wpf.RoutedCommands.Greeter"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Wpf.RoutedCommands"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.CommandBindings>
<CommandBinding Command="{x:Static local:Commands.SayHi}" Executed="cmdSayHi" CanExecute="cmdCanSayHi"/>
</UserControl.CommandBindings>
<Grid>
<Label x:Name="Label" />
</Grid>
Код приветствия:
using System.Windows.Input;
namespace Wpf.RoutedCommands
{
public partial class Greeter
{
public Greeter()
{
InitializeComponent();
}
private void cmdSayHi(object sender, ExecutedRoutedEventArgs e) => SayHi();
private void cmdCanSayHi(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = true;
public void SayHi() => Label.Content = "Hi!";
}
}
Если вы создадите проект WPF и воспользуетесь вышеизложенным, вы увидите, что кнопка в главном окне отключена. Отладка показывает, что Greeter.cmdCanSayHi
метод никогда не вызывается.
Если вы раскомментируете спящий XAML в главном окне, все работает. Итак: Почему я могу связываться с командами из окна, но не из дочерних элементов управления? Это связано с временем рендеринга или что-то?
1 ответ
RoutedCommand
ищет визуальное дерево из сфокусированного элемента и вверх для элемента, который имеет соответствующий CommandBinding
а затем выполняет Execute
делегат для этого конкретного CommandBinding
,
Ваш UserControl
расположен ниже Button
в дереве элементов.