[英]WPF: How to implement Clear command
我正在学习 WPF。
在其中一个练习中,我有一个文本框和按钮剪切和粘贴。 以下内容足以实现剪切和粘贴功能:
XAML:
<DockPanel>
<WrapPanel DockPanel.Dock="Top" Margin="3">
<Button Command="ApplicationCommands.Cut"
CommandTarget="{Binding ElementName=txtEditor}"
Width="60">
_Cut
</Button>
<Button Command="ApplicationCommands.Paste"
CommandTarget="{Binding ElementName=txtEditor}"
Width="60" Margin="3,0">
_Paste<
/Button>
</WrapPanel>
<TextBox AcceptsReturn="True" Name="txtEditor" />
</DockPanel>
当按下时,按钮 Cut 在名为txtEditor
的 TextBox 上执行ApplicationCommands.Cut
。 需要时,按钮会询问名称为 textEditor 的 TextBox 是否可以执行剪切命令,当按下时,它将命令 textEditor 执行剪切命令。
非常坦率的。 它工作正常。
只是为了好玩,我想实现另一个按钮:清除。 当按下它应该清除文本框。 Textbox 类有一个方法 Clear。
<Button Command="ApplicationCommands.Clear"
CommandTarget="{Binding ElementName=txtEditor}"
Width="60">
Clear
</Button>
唉,这行不通。 ApplicationCommands
没有Clear
。 我应该按照本示例中的建议实施自定义命令吗?
我尝试了以下方法:
我在我的窗口中实现了 CanExecute 和 Executed 方法:
public partial class CustomCommandSample : Window
{
public CustomCommandSample()
{
InitializeComponent();
}
private void ClearCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void ClearCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
txtEditor.Clear();
}
}
静态 CustomCommands 类:
public static class CustomCommands
{
public static RoutedUICommand Clear => new RoutedUICommand (
"Clear",
"Clear",
typeof(CustomCommands));
}
最后是 XAML:(注意:这个项目中的类位于命名空间 WpfCommandDemo 中。Xaml 将其称为Local
)
<Window x:Class="WpfTutorialSamples.Commands.UsingCommandsSample"
xmlns="...
xmlns:local="clr-namespace:WpfCommandDemo"
Title="UsingCommandsSample" Height="100" Width="200">
<Window.CommandBindings>
<CommandBinding Command="CustomCommands.Clear"
CanExecute="ClearCommand_CanExecute"
Executed="ClearCommand_Executed" />
</Window.CommandBindings>
<DockPanel>
<WrapPanel DockPanel.Dock="Top" Margin="3">
<Button Command="CustomCommands.Clear"
CommandTarget="{Binding ElementName=txtEditor}"
Width="60">
Clear
</Button>
... (other buttons: cut / paste, as above
</WrapPanel>
<TextBox AcceptsReturn="True" Name="txtEditor" />
</DockPanel>
尽管可以编译,但 CustomCommandSample 的构造函数会抛出 XamlParseException:
Type reference cannot find type named
'{http://schemas.microsoft.com/winfx/2006/xaml/presentation}CustomCommands'.
我应该使用自定义命令解决问题吗? 我应该改变什么? 或者我完全错了,我应该以不同的方式解决这个问题
要在 XAML 中使用 CustomCommands,您需要添加对它的引用。 在元素中,添加一行:
xmlns:custom="clr-namespace:MyApplication.NamespaceWithCustomInIt"
根据需要替换命名空间值。 然后您应该能够在 XAML 中的任何位置引用 CustomCommands 作为custom:CustomCommands
(可能需要绑定,我稍后会检查)。
我应该使用自定义命令解决问题吗?
是的。 这是如何使用模型-视图-视图模型(MVVM)设计模式是在开发基于UI应用程序XAML推荐使用的设计模式来解决这个问题。
来自这篇博文:
WPF 提供了
ICommand
接口的两种实现;System.Windows.Input.RoutedCommand
和System.Windows.Input.RoutedUICommand
其中后者是前者的子类,它只是添加了一个描述命令的Text
属性。 但是,这两种实现都不特别适合在视图模型中使用,因为它们从焦点元素开始搜索可视化树,并向上搜索在其CommandBindings
集合中具有匹配System.Windows.Input.CommandBinding
对象的元素,然后执行此特定CommandBinding
的Execute
委托。 由于命令逻辑应驻留在视图模型中,因此您不希望在视图中设置CommandBinding
以将命令连接到可视元素。 相反,您可以通过创建一个实现ICommand
的类来创建自己的命令。 下面的实现是调用Execute
和CanExecute
方法的委托的常见实现:
public class DelegateCommand: System.Windows.Input.ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public DelegateCommand(Action<object> execute)
: this(execute, null) { }
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null ? true : _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
一旦你有了ICommand
接口的实现,它就很容易在你的视图模型中使用:
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
ClearCommand = new DelegateCommand(Clear);
}
private string _text;
public string Text
{
get { return _text; }
set { _text = value; NotifyPropertyChanged(); }
}
public ICommand ClearCommand { get; }
private void Clear(object parameter)
{
Text = string.Empty;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
在视图中,您只需绑定到视图模型的属性:
<TextBox AcceptsReturn="True" Name="txtEditor" Text="{Binding Text}" />
<Button Content="Clear" Command="{Binding ClearCommand}" />
只需记住将视图的DataContext
设置为视图模型的实例,以便绑定工作:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.