微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

wpf 按钮始终禁用使用 CommandBinding、CanExecute=True 和 IsEnabled=True

如何解决wpf 按钮始终禁用使用 CommandBinding、CanExecute=True 和 IsEnabled=True

修正:很抱歉在第一个版本中遗漏了一些重要的描述,现在问题应该是明确定义的:

所以我正在制作一个具有以下视图的玩具 CAD 程序:

  1. 主窗口.xaml
  2. 自定义用户控件.xaml

CustomizedUserControl 是 MainWindow 中的一个 Tab,其 DataContext 在 MainWindow.xaml 中定义为:

 <Window.Resources>
        <DataTemplate DataType="{x:Type local:CustomizedTabClass}">
            <local:UserControl1/>
        </DataTemplate>
 </Window.Resources>

而 CustomizedUserControl.xaml 提供了一个画布和一个按钮,因此当按下按钮时,用户应该能够在画布上绘图。如以下代码所示,Canvas 的内容由 dataContext 准备,“tabs:CustomizedTabClass”。

CustomizedUserControl.xaml


<CustomizedUserControl x:Name="Views.CustomizedUserControl11"
...
>
<Button ToolTip="Lines (L)" BorderThickness="2"
                        Command="{Binding ElementName=CustomizedUserControl11,Path=DrawingCommands.LinesChainCommand}"
                        IsEnabled="True"
                        Content = "{Binding ElementName=CustomizedUserControl11,Path=DrawingCommands.Button1Name}">
</Button>
...
<canvas x:Name="CADCanvas"
        Drawing="{Binding Drawing,Mode=TwoWay}" >
</canvas>

还值得注意的是,我在所有类中都使用了外部库 Fody/PropertyChanged,因此无需进一步编程即可注入属性通知

CustomizedUserControl.xaml.cs

using PropertyChanged;
using System.ComponentModel;
using System.Windows.Controls;

[AddINotifyPropertyChangedInterface]
public partial class CustomizedUserControl: Usercontrol,INotifyPropertyChanged{
  public CADDrawingCommands DrawingCommands { get; set; }
  public CustomizedUserControl()
  {
      InitializeComponent();
      DrawingCommands = new CADDrawingCommands(this);
      DrawingCommands.Button1Name = "yeahjojo"; //For testing data binding
  }
  public event PropertyChangedEventHandler PropertyChanged = (sender,e) => { };

}

CADDrawingCommands.cs

using PropertyChanged;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows;

[AddINotifyPropertyChangedInterface]
public class CADDrawingCommands : INotifyPropertyChanged{
  UserControl _drawableTab;
  public string Button1Name { get; set; } = "TestForDataBinding";
  public RoutedCommand LinesChainCommand { get; set; } = new RoutedCommand();
  public CADDrawingCommands(UserControl dTab){
        _drawableTab = dTab;
        CommandBinding lineCommandBinding = new CommandBinding(LinesChainCommand,(object sender,ExecutedRoutedEventArgs e) =>
             {
                 MessageBox.Show("Test");
                 //Draw on canvas inside CustomizedUserControl (modify Drawing property in CustomizedTabClass)
             },CanExecuteRoutedEventArgs e) => { e.CanExecute = true; });

            _drawableTab.CommandBindings.Add(lineCommandBinding);       

        }
 public event PropertyChangedEventHandler PropertyChanged = (sender,e) => { };

}

Button 的内容设置正确,因为我可以读取 Button1Name 中定义的字符串:

enter image description here

因此我认为命令的数据绑定也可以。 IsEnabled 已设置为 true,CommandBinding 的 CanExecute 将仅返回 true。

为什么我的按钮仍然呈灰色且无法点击?

如果我在 Window 而不是 UserControl 中定义按钮(并将 Window 的数据上下文设置为它自己的代码,该按钮将是可点击的!为什么?

感谢您的时间!希望有人能帮助我,因为我的想法和参考资料都用完了。

解决方法

如果您完整地展示了您的代码,那么我会发现其中存在以下问题:

  1. 您为 DrawingCommands 属性设置的值不正确。 在此属性中,您不会引发 PropertyChanged。 Button 中的绑定在 InitializeComponent() 方法中初始化。此时属性为空,给它赋值时,绑定找不到。

有两种方法可以解决这个问题:

  • 提高属性中的PropertyChanged
  • 如果您在构造函数中设置了一次属性值,则立即在初始化程序中设置它。使属性“只读”。在我看来,这种方式更好。
  public CADDrawingCommands DrawingCommands { get; }
  public FileEditTabUserControl()
  {
      DrawingCommands = new CADDrawingCommands(this);

      InitializeComponent();
      DrawingCommands.Button1Name = "yeahjojo"; //For testing data binding
  }

  1. 您有一个按钮绑定到 DrawingCommands.LinesChainCommand 属性中的命令。 但是对于这个属性,你分配了一个 = new RoutedCommand () 路由命令的空实例。 这看起来毫无意义。 如果您需要可路由的命令,请在“只读”静态属性中创建它。 这将使在 XAML 中使用更容易:
    public static RoutedCommand LinesChainCommand { get; }  = new RoutedCommand();
<Button ToolTip="Lines (L)" BorderThickness="2"
                        Command="{x:Static local:DrawingCommands.LinesChainCommand}"
                        IsEnabled="True"
                        Content = "{Binding ElementName=CustomizedUserControl11,Path=DrawingCommands.Button1Name}">
</Button>
  1. CADDrawingCommands 属性中引发 PropertyChanged 在您的代码中也不可见。 如果它真的不存在,那么绑定也不知道改变属性值。
,

做了最简单的例子。
一切正常。
BaseInpc 是我从这里简单的 INotifyPropertyChanged 实现:BaseInpc

using Simplified;
using System.Windows;
using System.Windows.Input;

namespace CustomizedUserControlRoutedCommand
{
    public class CADDrawingCommands : BaseInpc
    {
        UIElement _drawableTab;
        private string _button1Name = "TestForDataBinding";

        public string Button1Name { get => _button1Name; set => Set(ref _button1Name,value); }
        public static RoutedCommand LinesChainCommand { get; } = new RoutedCommand();
        public CADDrawingCommands(UIElement dTab)
        {
            _drawableTab = dTab;
            CommandBinding lineCommandBinding = new CommandBinding(LinesChainCommand,(object sender,ExecutedRoutedEventArgs e) =>
                 {
                     MessageBox.Show("Test");
                     //Draw on canvas inside CustomizedUserControl (modify Drawing property in CustomizedTabClass)
                 },CanExecuteRoutedEventArgs e) => { e.CanExecute = true; });

            _drawableTab.CommandBindings.Add(lineCommandBinding);
        }
    }
}
<UserControl x:Name="CustomizedUserControl11" x:Class="CustomizedUserControlRoutedCommand.CustomizedUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CustomizedUserControlRoutedCommand"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Button ToolTip="Lines (L)" BorderThickness="2"
                        Command="{x:Static local:CADDrawingCommands.LinesChainCommand}"
                        IsEnabled="True"
                        Content = "{Binding ElementName=CustomizedUserControl11,Path=DrawingCommands.Button1Name}">
        </Button>
    </Grid>
</UserControl>
using System.Windows.Controls;

namespace CustomizedUserControlRoutedCommand
{
    public partial class CustomizedUserControl : UserControl
    {
        public CADDrawingCommands DrawingCommands { get; }
        public CustomizedUserControl()
        {
            DrawingCommands = new CADDrawingCommands(this);

            InitializeComponent();
            DrawingCommands.Button1Name = "yeahjojo"; //For testing data binding
        }
    }
}

<Window x:Class="CustomizedUserControlRoutedCommand.TestCustomizedUserControlWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CustomizedUserControlRoutedCommand"
        mc:Ignorable="d"
        Title="TestCustomizedUserControlWindow" Height="450" Width="800">
    <Grid>
        <local:CustomizedUserControl/>
    </Grid>
</Window>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。