如何解决wpf 按钮始终禁用使用 CommandBinding、CanExecute=True 和 IsEnabled=True
修正:很抱歉在第一个版本中遗漏了一些重要的描述,现在问题应该是明确定义的:
所以我正在制作一个具有以下视图的玩具 CAD 程序:
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 中定义的字符串:
因此我认为命令的数据绑定也可以。 IsEnabled 已设置为 true,CommandBinding 的 CanExecute 将仅返回 true。
为什么我的按钮仍然呈灰色且无法点击?
如果我在 Window 而不是 UserControl 中定义按钮(并将 Window 的数据上下文设置为它自己的代码,该按钮将是可点击的!为什么?
感谢您的时间!希望有人能帮助我,因为我的想法和参考资料都用完了。
解决方法
如果您完整地展示了您的代码,那么我会发现其中存在以下问题:
- 您为 DrawingCommands 属性设置的值不正确。
在此属性中,您不会引发 PropertyChanged。
Button 中的绑定在
InitializeComponent()
方法中初始化。此时属性为空,给它赋值时,绑定找不到。
有两种方法可以解决这个问题:
- 提高属性中的PropertyChanged;
- 如果您在构造函数中设置了一次属性值,则立即在初始化程序中设置它。使属性“只读”。在我看来,这种方式更好。
public CADDrawingCommands DrawingCommands { get; }
public FileEditTabUserControl()
{
DrawingCommands = new CADDrawingCommands(this);
InitializeComponent();
DrawingCommands.Button1Name = "yeahjojo"; //For testing data binding
}
- 您有一个按钮绑定到
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>
- 在 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 举报,一经查实,本站将立刻删除。