今天早上我问了一个问题here并且做了一个简单的工作示例,给了我一个不同于预期的行为。为什么DataBinding不会传播到UserControl
全工作样品在GitHub。主要部分代码如下。
在这种情况下,如果UserControl直接用作窗口的子窗口,则该命令永远不会传播到任何UserControl。如果UserControl用作ListBox ItemTemplate的DataTemplate,它也不起作用。
我还包括一个黑客按钮来解决命令到达UserControls的问题。黑客来自StackOverflow。
但是使用hack并没有解释为什么UserControl没有收到命令(没有它)并且使用这个hack也破坏了良好编码的第一条规则:“高内聚和低耦合”。应该在窗口代码中使用hack以便管理UserControl中的Command,我的想法是它应该在默认情况下发生。
为什么命令不会默认传播给UserControl,我该怎么做才能以干净的方式将命令传播到UserControl?
注意:在UserControl中只使用一个CommandBinding(删除一个或另一个)不能解决问题。
部分代码:
<Window x:Class="CommandRoutingIntoItemTemplate.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:CommandRoutingIntoItemTemplate"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<local:UserControlTest></local:UserControlTest>
<ListBox Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Aqua" BorderThickness="2">
<local:UserControlTest></local:UserControlTest>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Items>
<system:String>1</system:String>
<system:String>2</system:String>
</ListBox.Items>
</ListBox>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<Button Command="local:Commands.CommandTest">Put focus on TestBlock and click here to see if command occurs</Button>
<Button Click="AddHack">Hack</Button>
</StackPanel>
</Grid>
</Window>
用户控件:
<UserControl x:Class="CommandRoutingIntoItemTemplate.UserControlTest"
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:CommandRoutingIntoItemTemplate"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.CommandBindings>
<CommandBinding Command="local:Commands.CommandTest" CanExecute="CommandTestCanExecuteUserControl" Executed="CommandTestExecuteUserControl"></CommandBinding>
</UserControl.CommandBindings>
<Grid>
<TextBox Text="UserControlTest">
<TextBox.CommandBindings>
<CommandBinding Command="local:Commands.CommandTest" CanExecute="CommandTestCanExecuteTextBox" Executed="CommandTestExecuteTextBox"></CommandBinding>
</TextBox.CommandBindings>
</TextBox>
</Grid>
</UserControl>
很好的解释!十分感谢!完美的作品。你知道我是否可以在UserControl上做些什么来确保它始终适用于每种类型的用法?虽然现在工作正常,但我可能想在其他地方使用我的UserControl,但我必须记住这一点。这听起来是一个更好的解决方案,只在一个常见的地方编写代码(UserControl),以确保在每种情况下的正确使用。 –
我也用menuItem测试过,它工作正常可能是因为Menu元素有你提出给我的修正:FocusManager.IsFocusScope设置为true?这是我必须知道和记住的事情;-)? –
@EricOuellet完全正确。 MenuItems显示在具有自己的焦点范围的弹出窗口中。 – ghord