2009-05-22 3 views
3

はい、私はそれが奇妙に聞こえるのは分かっていますが、それは問題ではありません。 PrintScreenキーまたはPauseキーを押しても、CanExecute fireを実行しても、すべてで動作します。だからドラッグドロップをした後、それを発射させるためには、マウスクリック、フォーカス、キーを押すなど、何か他のことをしなければなりません。これによりイベントが発生し、Executeが実行されます。とにかく、私のコードは、私はそれが長いことを知っているが、それはあなたが私を助けるのに役立ちます。WPFドラッグアンドドロップが発動しない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

関連する問題