2009-05-22 2 views
3

Да, я знаю, это звучит странно, но это не так, вопрос в том, почему и если есть работа. Он работает со всем, даже когда вы нажимаете клавиши PrintScreen или Pause, запускается CanExecute. Поэтому, после того, как вы сделали перетаскивание, чтобы сделать это, вы должны сделать что-то еще, например, щелчок мышью, фокус, нажатие клавиши, что угодно. Это приведет к пожару события и позволит выполнить выполнение. Во всяком случае, вот мой код, я знаю, что он длинный, но он поможет вам помочь.WPF Drag n drop не срабатывает CommanBinding.CanExecute

Я нашел эту ошибку в нашем крупном главном проекте, поэтому я упростил это приложение, чтобы изолировать проблему.

XAML:

<Window x:Class="DragNDropCommands.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="485" SizeToContent="Width" Loaded="Window_Loaded"> 
    <Window.CommandBindings> 
     <CommandBinding Command="ApplicationCommands.New" CanExecute="NewCanExecute" Executed="NewExecuted" /> 
     <CommandBinding Command="ApplicationCommands.Save" CanExecute="SaveCanExecute" Executed="SaveExecuted" /> 
     <CommandBinding Command="ApplicationCommands.Undo" CanExecute="UndoCanExecute" Executed="UndoExecuted" /> 
     <CommandBinding Command="ApplicationCommands.Redo" CanExecute="RedoCanExecute" Executed="RedoExecuted" /> 
    </Window.CommandBindings> 
    <Grid Margin="8"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="Auto" /> 
     </Grid.ColumnDefinitions> 

     <Button Command="ApplicationCommands.New" Grid.Row="0" Grid.Column="0" FontWeight="Bold" Content="New" Width="80" Margin="8"></Button> 
     <Button Command="ApplicationCommands.Save" Grid.Row="0" Grid.Column="1" FontWeight="Bold" Content="Save" Width="80" Margin="8"></Button> 
     <Button Command="ApplicationCommands.Undo" Grid.Row="0" Grid.Column="2" FontWeight="Bold" Content="Undo" Width="80" Margin="8"></Button> 
     <Button Command="ApplicationCommands.Redo" Grid.Row="0" Grid.Column="3" FontWeight="Bold" Content="Redo" Width="80" Margin="8"></Button> 

     <CheckBox Grid.Row="1" Grid.Column="0" Margin="8" IsChecked="{Binding Path=AllowNew, Mode=TwoWay}">Allow New</CheckBox> 
     <CheckBox Grid.Row="1" Grid.Column="1" Margin="8" IsChecked="{Binding Path=AllowSave}">Allow Save</CheckBox> 
     <CheckBox Grid.Row="1" Grid.Column="2" Margin="8" IsChecked="{Binding Path=AllowUndo}">Allow Undo</CheckBox> 
     <CheckBox Grid.Row="1" Grid.Column="3" Margin="8" IsChecked="{Binding Path=AllowRedo}">Allow Redo</CheckBox> 

     <Label x:Name="labelDrag" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" BorderBrush="Black" BorderThickness="1" MouseDown="Label_MouseDown" 
       Background="LightBlue" HorizontalContentAlignment="Center" Margin="8">Drag this label...</Label> 
     <Label x:Name="labelDropNew" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" BorderBrush="Black" BorderThickness="1" Drop="labelDropNew_Drop" 
       Background="LightGray" HorizontalContentAlignment="Center" Margin="8" AllowDrop="True">...here to toggle AllowNew</Label> 
     <Label x:Name="labelDropSave" Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2" BorderBrush="Black" BorderThickness="1" Drop="labelDropSave_Drop" 
       Background="LightGray" HorizontalContentAlignment="Center" Margin="8" AllowDrop="True">...here to toggle AllowSave</Label> 

     <ListBox x:Name="listViewLog" Grid.Row="4" Grid.ColumnSpan="4" Margin="8" Width="500"> 
     </ListBox> 

     <Button Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2" Margin="8" Click="Button_Click">Clear list</Button> 
    </Grid> 
</Window> 

C#:

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 

namespace DragNDropCommands 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     private CommandControl commandControl = new CommandControl(); 
     private int canExecuteCount = 1; 

     public Window1() 
     { 
      InitializeComponent(); 
     } 

     private void Window_Loaded(object sender, RoutedEventArgs e) 
     { 
      this.DataContext = commandControl; 
     } 

     private void NewCanExecute(object sender, CanExecuteRoutedEventArgs e) 
     { 
      if (this.commandControl == null || listViewLog == null) 
       return; 

      e.CanExecute = this.commandControl.AllowNew; 

      listViewLog.Items.Add 
      (
       String.Format 
       (
        "{0} - NewCanExecute: {1} - commandControl.AllowNew: {2}", 
        canExecuteCount++, e.CanExecute, commandControl.AllowNew 
       ) 
      ); 
     } 

     private void NewExecuted(object sender, ExecutedRoutedEventArgs e) 
     { 
      MessageBox.Show("New executed"); 
     } 

     private void SaveCanExecute(object sender, CanExecuteRoutedEventArgs e) 
     { 
      if (this.commandControl == null || listViewLog == null) 
       return; 

      e.CanExecute = this.commandControl.AllowSave; 

      listViewLog.Items.Add 
      (
       String.Format 
       (
        "{0} - SaveCanExecute: {1} - commandControl.AllowSave: {2}", 
        canExecuteCount++, e.CanExecute, commandControl.AllowSave 
       ) 
      ); 
     } 

     private void SaveExecuted(object sender, ExecutedRoutedEventArgs e) 
     { 
      MessageBox.Show("Save executed"); 
     } 

     private void UndoCanExecute(object sender, CanExecuteRoutedEventArgs e) 
     { 
      if (this.commandControl == null || listViewLog == null) 
       return; 

      e.CanExecute = this.commandControl.AllowUndo; 

      listViewLog.Items.Add 
      (
       String.Format 
       (
        "{0} - UndoCanExecute: {1} - commandControl.AllowUndo: {2}", 
        canExecuteCount++, e.CanExecute, commandControl.AllowUndo 
       ) 
      ); 
     } 

     private void UndoExecuted(object sender, ExecutedRoutedEventArgs e) 
     { 
      MessageBox.Show("Undo executed"); 
     } 

     private void RedoCanExecute(object sender, CanExecuteRoutedEventArgs e) 
     { 
      if (this.commandControl == null || listViewLog == null) 
       return; 

      e.CanExecute = this.commandControl.AllowRedo; 

      listViewLog.Items.Add 
      (
       String.Format 
       (
        "{0} - RedoCanExecute: {1} - commandControl.AllowRedo: {2}", 
        canExecuteCount++, e.CanExecute, commandControl.AllowRedo 
       ) 
      ); 
     } 

     private void RedoExecuted(object sender, ExecutedRoutedEventArgs e) 
     { 
      MessageBox.Show("Redo executed"); 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      listViewLog.Items.Clear(); 
     } 

     private void Label_MouseDown(object sender, MouseButtonEventArgs e) 
     { 
      Label label = (Label)sender; 

      if(e.LeftButton == MouseButtonState.Pressed) 
       DragDrop.DoDragDrop(label, label, DragDropEffects.Move); 
     } 

     private void labelDropNew_Drop(object sender, DragEventArgs e) 
     { 
      this.commandControl.AllowNew = !this.commandControl.AllowNew; 
     } 

     private void labelDropSave_Drop(object sender, DragEventArgs e) 
     { 
      this.commandControl.AllowSave = !this.commandControl.AllowSave; 
     } 
    } 

    public class CommandControl : DependencyObject 
    { 
     public bool AllowNew 
     { 
      get { return (bool)GetValue(AllowNewProperty); } 
      set { SetValue(AllowNewProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for AllowNew. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty AllowNewProperty = 
      DependencyProperty.Register("AllowNew", typeof(bool), typeof(CommandControl), new UIPropertyMetadata(false)); 

     public bool AllowSave 
     { 
      get { return (bool)GetValue(AllowSaveProperty); } 
      set { SetValue(AllowSaveProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for AllowSave. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty AllowSaveProperty = 
      DependencyProperty.Register("AllowSave", typeof(bool), typeof(CommandControl), new UIPropertyMetadata(false)); 

     public bool AllowUndo 
     { 
      get { return (bool)GetValue(AllowUndoProperty); } 
      set { SetValue(AllowUndoProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for AllowUndo. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty AllowUndoProperty = 
      DependencyProperty.Register("AllowUndo", typeof(bool), typeof(CommandControl), new UIPropertyMetadata(false)); 

     public bool AllowRedo 
     { 
      get { return (bool)GetValue(AllowRedoProperty); } 
      set { SetValue(AllowRedoProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for AllowRedo. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty AllowRedoProperty = 
      DependencyProperty.Register("AllowRedo", typeof(bool), typeof(CommandControl), new UIPropertyMetadata(false)); 
    } 
} 

Вы должны быть в состоянии просто скопировать пасту и сделать несколько имен изменения (файлы, пространства имен), чтобы он работает. Мне очень понравилась бы ваша помощь, так как это заставляло меня сходить с ума, и теперь, когда я наконец обнаружил причину ошибки, я не знаю, что с этим делать.

Любое предложение действительно одобрено.

Заранее спасибо.

ответ

5

Только быстрое предложение:

Вы можете использовать CommandManager.InvalidateRequerySuggested() в перетаскивания обработчик события, чтобы заставить повторное выполнение CanExecute(). (Link)

+0

Ничего себе, что изящное решение. Спасибо огромное! – Carlo

+0

одну из этих вещей вы можете искать навсегда, если бы это было не для вас ;-) спасибо! – Dabblernl