WPF拖放不';t fire CommanBinding.CanExecute

WPF拖放不';t fire CommanBinding.CanExecute,wpf,drag-and-drop,Wpf,Drag And Drop,是的,我知道这听起来很奇怪,但事实并非如此,问题是为什么,以及是否有解决办法。它适用于任何情况,甚至当您点击打印屏幕或暂停键时,也可以执行触发。所以在做了一个拖放之后,为了让它启动,你必须做一些其他的事情,比如鼠标点击、聚焦、按键等等。这将触发事件,并允许执行。不管怎样,这是我的代码,我知道它很长,但它会帮助你帮助我 我在我们的大型主项目中发现了这个bug,所以我将它简化为这个小应用程序来隔离问题 XAML: 允许新的 允许保存 允许撤消 允许重做 拖动此标签。。。 …在这里切换AllowNe

是的,我知道这听起来很奇怪,但事实并非如此,问题是为什么,以及是否有解决办法。它适用于任何情况,甚至当您点击打印屏幕或暂停键时,也可以执行触发。所以在做了一个拖放之后,为了让它启动,你必须做一些其他的事情,比如鼠标点击、聚焦、按键等等。这将触发事件,并允许执行。不管怎样,这是我的代码,我知道它很长,但它会帮助你帮助我

我在我们的大型主项目中发现了这个bug,所以我将它简化为这个小应用程序来隔离问题

XAML:


允许新的
允许保存
允许撤消
允许重做
拖动此标签。。。
…在这里切换AllowNew
…在这里切换AllowSave
清除列表
C#:

使用系统;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
名称空间DragnDropCommand
{
/// 
///Window1.xaml的交互逻辑
/// 
公共部分类Window1:Window
{
private CommandControl CommandControl=new CommandControl();
私有int canExecuteCount=1;
公共窗口1()
{
初始化组件();
}
已加载私有无效窗口(对象发送器、路由目标)
{
this.DataContext=commandControl;
}
私有void NewCanExecute(对象发送方,canExecuteRouteEventArgs e)
{
if(this.commandControl==null | | listViewLog==null)
返回;
e、 CanExecute=this.commandControl.AllowNew;
listViewLog.Items.Add
(
字符串格式
(
“{0}-NewCanExecute:{1}-commandControl.AllowNew:{2}”,
canExecuteCount++,e.CanExecute,commandControl.AllowNew
)
);
}
私有void NewExecuted(对象发送方,ExecutedRoutedEventArgs e)
{
MessageBox.Show(“新执行”);
}
私有void SaveCanExecute(对象发送方,CanExecuteRoutedEventArgs e)
{
if(this.commandControl==null | | listViewLog==null)
返回;
e、 CanExecute=this.commandControl.AllowSave;
listViewLog.Items.Add
(
字符串格式
(
“{0}-SaveCanExecute:{1}-commandControl.AllowSave:{2}”,
canExecuteCount++,e.CanExecute,commandControl.AllowSave
)
);
}
私有void SaveExecuted(对象发送方,ExecutedRoutedEventArgs e)
{
MessageBox.Show(“保存已执行”);
}
私有void UndoCanExecute(对象发送方,CanExecuteRoutedEventArgs e)
{
if(this.commandControl==null | | listViewLog==null)
返回;
e、 CanExecute=this.commandControl.AllowUndo;
listViewLog.Items.Add
(
字符串格式
(
“{0}-UndoCanExecute:{1}-commandControl.AllowUndo:{2}”,
canExecuteCount++,e.CanExecute,commandControl.AllowUndo
)
);
}
私有void UndoExecuted(对象发送方,ExecutedRoutedEventArgs e)
{
MessageBox.Show(“撤销已执行”);
}
私有void RedoCanExecute(对象发送方,canexecuterouteEventArgs e)
{
if(this.commandControl==null | | listViewLog==null)
返回;
e、 CanExecute=this.commandControl.AllowRedo;
listViewLog.Items.Add
(
字符串格式
(
“{0}-RedoCanExecute:{1}-commandControl.AllowRedo:{2}”,
canExecuteCount++,e.CanExecute,commandControl.AllowRedo
)
);
}
private void RedoExecuted(对象发送方,ExecutedRoutedEventArgs e)
{
MessageBox.Show(“重做已执行”);
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
listViewLog.Items.Clear();
}
私有无效标签_MouseDown(对象发送器,MouseButtonEventArgs e)
{
标签=(标签)发送者;
如果(e.LeftButton==鼠标按钮状态。按下)
DragDrop.DoDragDrop(标签,标签,DragDropEffects.Move);
}
专用无效标签ELDROPNEW_Drop(对象发送器,DragEventArgs e)
{
this.commandControl.AllowNew=!this.commandControl.AllowNew;
}
私有无效标签ELDROPSAVE_Drop(对象发送方,DragEventArgs e)
{
this.commandControl.AllowSave=!this.commandControl.AllowSave;
}
}
公共类CommandControl:DependencyObject
{
公共场所许可
{
获取{return(bool)GetValue(AllowNewProperty);}
set{SetValue(AllowNewProperty,value);}
}
//使用DependencyProperty作为AllowNew的备份存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性AllowneProperty=
DependencyProperty.Register(“AllowNew”、typeof(bool)、typeof(CommandControl)、新UIPropertyMetadata(false));
公共布尔允许保存
{
获取{return(bool)GetValue(AllowSaveProperty);}
set{SetValue(AllowSaveProperty,value);}
}
//使用DependencyProperty作为AllowSave的备份存储。这将启用动画、样式、绑定等。。。
公共静态区域
<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>
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));
    }
}