我有一個用戶控件,如下圖所示,用於顯示主細節種類。帶有基本視圖模型的典型MVVM體系結構與CloseCommand一起完成。KeyBinding的困境
我想範圍一個KeyBinding,將在TabItem上執行關閉命令,只是不能讓它工作。
有趣的是,我可以得到它,如果我穿上PersonDetailView(的是,TabControl的可能顯示,如下圖所示兩種可能的用戶控件之一)的結合工作,但它應該在的TabControl或邊境地區的包含它。
有什麼建議嗎?
乾杯,
Berryl
用戶控件
<Grid>
<ListBox Style="{StaticResource ListBoxStyle}" />
<GridSplitter
HorizontalAlignment="Right" VerticalAlignment="Stretch" Grid.Column="1"
ResizeBehavior="PreviousAndNext" Width="5" Background="#FFBCBCBC" KeyboardNavigation.IsTabStop="False"
/>
<Border Grid.Column="2" Background="{StaticResource headerBrush}">
// ** THIS is the scope I want, but it doesn't work
<Border.InputBindings>
<KeyBinding Key="F4" Modifiers="Control" Command="{Binding CloseCommand}"/>
</Border.InputBindings>
<TabControl Style="{StaticResource TabControlStyle}" >
<TabControl.Resources>
<DataTemplate DataType="{x:Type personVm:PersonDetailVm}">
<local:PersonDetailView />
</DataTemplate>
<DataTemplate DataType="{x:Type orgVm:OrganizationDetailVm}">
<local:OrganizationDetailView />
</DataTemplate>
</TabControl.Resources>
</TabControl>
</Border>
</Grid>
TabItem的風格
<Style x:Key="OrangeTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border AllowDrop="true" ToolTip="{Binding DisplayName}">
<Border Name="Border" Background="Transparent" BorderBrush="Transparent" BorderThickness="1,1,1,0" CornerRadius="2,2,0,0">
<DockPanel x:Name="TitlePanel" TextElement.Foreground="{StaticResource FileTabTextBrush}">
<ctrl:GlyphButton
// ** This works as expected
Command="{Binding CloseCommand}" CommandParameter="{Binding}"
>
</ctrl:GlyphButton>
</DockPanel>
</Border>
// ** Can't get it to work from here either **
<Border.InputBindings>
<KeyBinding Command="{Binding CloseCommand}" Key="F4" Modifiers="Control" />
</Border.InputBindings>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
UPDATE
我茫然地設置的RoutedCommand在我的風格
<Style x:Key="OrangeTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="beh:RoutedCommandWire.RoutedCommand" Value="F4"/> **** ?? ****
<Setter Property="beh:RoutedCommandWire.ICommand" Value="{Binding CloseCommand}"/>
</Style>
這是我認爲答案代碼看起來像在C#
public class RoutedCommandWire
{
public static readonly DependencyProperty RoutedCommandProperty =
DependencyProperty.RegisterAttached("RoutedCommand", typeof(RoutedCommand), typeof(RoutedCommandWire), new PropertyMetadata(OnCommandChanged));
public static RoutedCommand GetRoutedCommand(DependencyObject d) { return (RoutedCommand) d.GetValue(RoutedCommandProperty); }
public static void SetRoutedCommand(DependencyObject d, RoutedCommand value) { d.SetValue(RoutedCommandProperty, value); }
public static readonly DependencyProperty ICommandProperty =
DependencyProperty.RegisterAttached("Iommand", typeof(ICommand), typeof(RoutedCommandWire));
public static ICommand GetICommand(DependencyObject d) { return (ICommand) d.GetValue(ICommandProperty); }
public static void SetICommand(DependencyObject d, ICommand value) { d.SetValue(ICommandProperty, value); }
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var fe = d as FrameworkElement;
if(fe==null) return;
if (e.OldValue != null) {
Detach(fe, (RoutedCommand) e.OldValue);
}
if (e.NewValue != null) {
Attach(fe, (RoutedCommand) e.NewValue, Execute, CanExecute);
}
}
private static void CanExecute(object sender, CanExecuteRoutedEventArgs e) {
var depObj = sender as DependencyObject;
if (depObj == null) return;
var command = GetICommand(depObj);
if (command == null) return;
e.CanExecute = command.CanExecute(e.Parameter);
e.Handled = true;
}
private static void Execute(object sender, ExecutedRoutedEventArgs e)
{
var depObj = sender as DependencyObject;
if (depObj == null) return;
var command = GetICommand(depObj);
if (command == null) return;
command.Execute(e.Parameter);
e.Handled = true;
}
public static void Detach(FrameworkElement fe, RoutedCommand command) {
var bindingCollection = fe.CommandBindings;
if (bindingCollection.Count == 0) return;
var matches = bindingCollection.Cast<CommandBinding>().Where(binding => binding.Equals(command));
foreach (var binding in matches) {
bindingCollection.Remove(binding);
}
}
public static void Attach(FrameworkElement fe, RoutedCommand command,
ExecutedRoutedEventHandler executedHandler, CanExecuteRoutedEventHandler canExecuteHandler, bool preview = false)
{
if (command == null || executedHandler == null) return;
var binding = new CommandBinding(command);
if (preview)
{
binding.PreviewExecuted += executedHandler;
if (canExecuteHandler != null)
{
binding.PreviewCanExecute += canExecuteHandler;
}
}
else
{
binding.Executed += executedHandler;
if (canExecuteHandler != null)
{
binding.CanExecute += canExecuteHandler;
}
}
fe.CommandBindings.Add(binding);
}
}
哪個類具有'CloseCommand'屬性? – 2012-06-09 07:11:48
我想你會在這裏找到一個解決方案http://stackoverflow.com/questions/10365582/how-to-implement-commands-to-use-ancestor-methods-in-wpf/10390564#10390564 – Phil
@funkett。我所有的視圖模型都是這樣做的,儘管這裏感興趣的是PersonDetailVm和OrganizationDetailVm。乾杯 – Berryl