繁体   English   中英

WPF:如何实现清除命令

[英]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.RoutedCommandSystem.Windows.Input.RoutedUICommand其中后者是前者的子类,它只是添加了一个描述命令的Text属性。 但是,这两种实现都不特别适合在视图模型中使用,因为它们从焦点元素开始搜索可视化树,并向上搜索在其CommandBindings集合中具有匹配System.Windows.Input.CommandBinding对象的元素,然后执行此特定CommandBindingExecute委托。 由于命令逻辑应驻留在视图模型中,因此您不希望在视图中设置CommandBinding以将命令连接到可视元素。 相反,您可以通过创建一个实现ICommand的类来创建自己的命令。 下面的实现是调用ExecuteCanExecute方法的委托的常见实现:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM