2015-02-05 2 views
0

У меня проблема с привязкой в ​​KeyBinding в WPF. Я разрабатываю проект .net 3.5 с использованием WPF с шаблоном MVVM. Я должен запускать команду, когда будет напечатано какое-то письмо. К сожалению, Command и CommandParameter не являются зависимыми свойствами в этой версии .net, и я не могу привязываться к ним. Поэтому я написал прикрепленные свойства, чтобы назначить параметр команды и команды из моей модели представления. Но привязка к ним не работает, когда я изменяю привязку к тексту (в параметре команды) CommandBindingParameterChanged будет расти, но это не происходит, когда есть привязка к параметру. Я устал задавать имя окна и передавать его привязке, но он также не работал. Но когда я назначу ту же команду кнопке, она отлично работает. Вот мой фрагмент кода:Связанная привязка свойств в KeyBinding

Прикрепленные свойства:

public class Helper 
{ 
    public static readonly DependencyProperty CommandBindingProperty = DependencyProperty.RegisterAttached("CommandBinding", typeof(ICommand), typeof(Helper), new FrameworkPropertyMetadata(default(ICommand), FrameworkPropertyMetadataOptions.None, CommandChanged)); 

    public static ICommand GetCommandBinding(DependencyObject o) 
    { 
     return (ICommand)o.GetValue(CommandBindingProperty); 
    } 
    public static void SetCommandBinding(DependencyObject o, ICommand value) 
    { 
     o.SetValue(CommandBindingProperty, value); 
    } 

    private static void CommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var input = d as InputBinding; 

     input.Command = (ICommand)e.NewValue; 
    } 


    public static readonly DependencyProperty CommandBindingParameterProperty = DependencyProperty.RegisterAttached("CommandBindingParameter", typeof(object), typeof(Helper), new PropertyMetadata(CommandParameterChanged)); 

    private static void CommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var input = d as InputBinding; 
     if (input != null) 
      input.CommandParameter = e.NewValue; 
    } 
    public static object GetCommandBindingParameter(DependencyObject o) 
    { 
     return o.GetValue(CommandBindingParameterProperty); 
    } 
    public static void SetCommandBindingParameter(DependencyObject o, object value) 
    { 
     o.SetValue(CommandBindingParameterProperty, value); 
    } 
} 

ViewModel

public class MainWindowViewModel : ViewModelBase 
{ 

    private string _text; 

    public string Text 
    { 
     get { return _text; } 
     set 
     { 
      _text = value; 
      RaisePropertyChanged("Text"); 
     } 
    } 


    private bool _parameter; 
    public bool Parameter 
    { 
     get { return _parameter; } 
     set 
     { 
      _parameter = value; 
      RaisePropertyChanged("Parameter"); 
     } 
    } 

    public MainWindowViewModel() 
    { 
     Parameter = true; 
    } 

    private RelayCommand<bool> _someCommand; 

    public ICommand SomeCommand 
    { 
     get { return _someCommand ?? (_someCommand = new RelayCommand<bool>(Execute, CanExecute)); } 
    } 

    private bool CanExecute(bool arg) 
    { 
     return arg; 
    } 

    private void Execute(bool obj) 
    { 
     //do something 
    } 
} 

XAML:

<Window x:Class="Test.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525" 
    xmlns:local="clr-namespace:Test" 
    Name="Window" 
    DataContext="{Binding Main, Source={StaticResource Locator}}" 
    > 
<Grid> 
    <StackPanel> 
     <TextBox Text="{Binding Text}"> 
      <TextBox.InputBindings> 
       <KeyBinding Key="A" local:Helper.CommandBinding="{Binding DataContext.SomeCommand, ElementName=Window}" local:Helper.CommandBindingParameter="{Binding DataContext.Parameter, ElementName=Window}"/> 
      </TextBox.InputBindings> 
     </TextBox> 
     <Button Content="SomeButton" Command="{Binding SomeCommand}" CommandParameter="{Binding Parameter}"/> 
    </StackPanel> 
</Grid> 

ответ

0

вы можете попробовать это решение.

Использовать Blend 3 Interactions, т. Е. Добавить System.Windows.Interactivity & Microsoft.Expression.Interactions.dll как ссылку в ваш проект. Я проверил изменения ниже. Выполнить метод (определено в ViewModel) называется текстовое поле движение введенные

Модифицированный XAML:.

<Window x:Class="Test.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525" 
    xmlns:local="clr-namespace:Test" 
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    Name="Window"> 
    <Window.DataContext> 
     <local:MainWindowViewModel/> 
    </Window.DataContext> 
    <Grid> 
     <StackPanel> 
      <TextBox> 
       <i:Interaction.Triggers> 
        <i:EventTrigger EventName="KeyUp"> 
         <local:CommandAction Command="{Binding Path=SomeCommand}" CommandParameter="{Binding Path=Parameter}" /> 
        </i:EventTrigger> 
       </i:Interaction.Triggers> 
      </TextBox> 
     </StackPanel> 
    </Grid> 
</Window> 

CommandAction.CS: Вместо Helper, используйте CommandAction. CommandAction находится на this location

using System; 
using System.ComponentModel; 
using System.Windows; 
using System.Windows.Input; 
using Microsoft.Expression.Interactivity; 
using System.Windows.Interactivity; 

namespace Test 
{ 
    /// <summary> 
    /// The CommandAction allows the user to route a FrameworkElement's routed event to a Command. 
    /// For instance this makes it possible to specify--in Xaml--that right-clicking on a Border 
    /// element should execute the Application.Close command (this example may not make much sense, 
    /// but it does illustrate what's possible). 
    /// 
    /// CommandParameter and CommandTarget properties are provided for consistency with the Wpf 
    /// Command pattern. 
    /// 
    /// The action's IsEnabled property will be updated according to the Command's CanExecute value. 
    /// 
    /// In addition a SyncOwnerIsEnabled property allows the user to specify that the owner element 
    /// should be enabled/disabled whenever the action is enabled/disabled. 
    /// </summary> 
    public class CommandAction : TargetedTriggerAction<FrameworkElement>, ICommandSource 
    { 
     #region Properties to Expose 
     [Category("Command Properties")] 
     public ICommand Command 
     { 
      get { return (ICommand)GetValue(CommandProperty); } 
      set { SetValue(CommandProperty, value); } 
     } 

     public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
      "Command", typeof(ICommand), typeof(CommandAction), new PropertyMetadata(
       (ICommand)null, OnCommandChanged)); 

     [Category("Command Properties")] 
     public object CommandParameter 
     { 
      get { return (object)GetValue(CommandParameterProperty); } 
      set { SetValue(CommandParameterProperty, value); } 
     } 

     public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
      "CommandParameter", typeof(object), typeof(CommandAction), new PropertyMetadata()); 

     [Category("Command Properties")] 
     public IInputElement CommandTarget 
     { 
      get { return (IInputElement)GetValue(CommandTargetProperty); } 
      set { SetValue(CommandTargetProperty, value); } 
     } 

     public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register(
      "CommandTarget", typeof(IInputElement), typeof(CommandAction), new PropertyMetadata()); 

     [Category("Command Properties")] 
     public bool SyncOwnerIsEnabled 
     { 
      get { return (bool)GetValue(SyncOwnerIsEnabledProperty); } 
      set { SetValue(SyncOwnerIsEnabledProperty, value); } 
     } 

     /// <summary> 
     /// When SyncOwnerIsEnabled is true then changing CommandAction.IsEnabled will automatically 
     /// update the owner (Target) IsEnabled property. 
     /// </summary> 
     public static readonly DependencyProperty SyncOwnerIsEnabledProperty = DependencyProperty.Register(
      "SyncOwnerIsEnabled", typeof(bool), typeof(CommandAction), new PropertyMetadata()); 

     #endregion 

     #region Command implementation 

     /// <summary> 
     /// This is a strong reference to the Command.CanExecuteChanged event handler. The commanding 
     /// system uses a weak reference and if we don't enforce a strong reference then the event 
     /// handler will be gc'ed. 
     /// </summary> 
     private EventHandler CanExecuteChangedHandler; 

     private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var action = (CommandAction)d; 
      action.OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue); 
     } 

     private void OnCommandChanged(ICommand oldCommand, ICommand newCommand) 
     { 
      if (oldCommand != null) 
       UnhookCommand(oldCommand); 
      if (newCommand != null) 
       HookCommand(newCommand); 
     } 

     private void UnhookCommand(ICommand command) 
     { 
      command.CanExecuteChanged -= CanExecuteChangedHandler; 
      UpdateCanExecute(); 
     } 

     private void HookCommand(ICommand command) 
     { 
      // Save a strong reference to the Command.CanExecuteChanged event handler. The commanding 
      // system uses a weak reference and if we don't save a strong reference then the event 
      // handler will be gc'ed. 
      CanExecuteChangedHandler = new EventHandler(OnCanExecuteChanged); 
      command.CanExecuteChanged += CanExecuteChangedHandler; 
      UpdateCanExecute(); 
     } 

     private void OnCanExecuteChanged(object sender, EventArgs e) 
     { 
      UpdateCanExecute(); 
     } 

     private void UpdateCanExecute() 
     { 
      if (Command != null) 
      { 
       RoutedCommand command = Command as RoutedCommand; 
       if (command != null) 
        IsEnabled = command.CanExecute(CommandParameter, CommandTarget); 
       else 
        IsEnabled = Command.CanExecute(CommandParameter); 
       if (Target != null && SyncOwnerIsEnabled) 
        Target.IsEnabled = IsEnabled; 
      } 
     } 

     #endregion 

     protected override void Invoke(object o) 
     { 
      if (Command != null) 
      { 
       var command = Command as RoutedCommand; 
       if (command != null) 
        command.Execute(CommandParameter, CommandTarget); 
       else 
        Command.Execute(CommandParameter); 
      } 
     } 
    } 
} 

Скриншот: если System.Windows.Interactivity & Microsoft.Expression.Interactions.dll отсутствуют в вашей среде, необходимо установить смесь. Blend очень прост в использовании и не требует много времени.

Screenshot

Смежные вопросы