WPF Drag n drop fails CommanBinding.CanExecute

Yes, I know that sounds weird, but it doesn't, the question is why, and if there is work. It works with everything, even when you press the PrintScreen or Pause keys, CanExecute starts. Therefore, after you have done a drag and drop to do this, you must do something else, such as a mouse click, focus, key press, whatever. This will cause a fire event and allow execution. Anyway, here is my code, I know this for a long time, but it will help you to help me.

I found this error in our large main project, so I simplified this application to isolate the problem.

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>

FROM#:

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));
    }
}

(, ), . , , , , , .

.

.

+3
1

:

CommandManager.InvalidateRequerySuggested() , CanExecute(). ()

+5

Source: https://habr.com/ru/post/1708863/


All Articles