由子元素绑定的 RoutedCommands 从不触发
RoutedCommands bound by sub elements never fire
我正在尝试了解 WPF 中的 RoutedCommands。我喜欢它们如何减少不同 UI 元素与模型之间的耦合,但我似乎无法使绑定适用于 window 的子级自定义控件。我想这对于你们中的任何一个 WPF 向导来说都是一些简单的信誉! :-)
下面是一些可以试用的示例代码:
路由命令:
using System.Windows.Input;
namespace Wpf.RoutedCommands
{
public static class Commands
{
public static readonly RoutedCommand SayHi = new RoutedCommand();
}
}
主要windowXAML:
<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>
主要window代码:
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 项目并使用上面的项目,您将看到主 window 中的按钮被禁用。调试显示 Greeter.cmdCanSayHi
方法永远不会被调用。
如果您取消注释 main window 中的休眠 XAML 一切正常。所以:为什么我可以绑定到来自 window 的命令而不是来自其子控件的命令?跟渲染时间有关系吗?
A RoutedCommand
从聚焦元素搜索可视化树,然后 up 查找具有匹配 CommandBinding
的元素,然后执行 Execute
代表这个特定的 CommandBinding
.
您的UserControl
位于元素树中Button
下方。
我正在尝试了解 WPF 中的 RoutedCommands。我喜欢它们如何减少不同 UI 元素与模型之间的耦合,但我似乎无法使绑定适用于 window 的子级自定义控件。我想这对于你们中的任何一个 WPF 向导来说都是一些简单的信誉! :-)
下面是一些可以试用的示例代码:
路由命令:
using System.Windows.Input;
namespace Wpf.RoutedCommands
{
public static class Commands
{
public static readonly RoutedCommand SayHi = new RoutedCommand();
}
}
主要windowXAML:
<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>
主要window代码:
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 项目并使用上面的项目,您将看到主 window 中的按钮被禁用。调试显示 Greeter.cmdCanSayHi
方法永远不会被调用。
如果您取消注释 main window 中的休眠 XAML 一切正常。所以:为什么我可以绑定到来自 window 的命令而不是来自其子控件的命令?跟渲染时间有关系吗?
A RoutedCommand
从聚焦元素搜索可视化树,然后 up 查找具有匹配 CommandBinding
的元素,然后执行 Execute
代表这个特定的 CommandBinding
.
您的UserControl
位于元素树中Button
下方。