【问题标题】:WPF mvvm Button (ICommand) CanExecute not WorkingWPF mvvm按钮(ICommand)CanExecute不起作用
【发布时间】:2019-11-01 18:37:14
【问题描述】:

我有这个 xaml 和这个代码。 我的问题是确认没有改变。 CanExecute 只执行一次。

    <Label Grid.Row="0" Grid.Column="0"  Content="Connection String"/>
    <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding  Path=ConnectionString,UpdateSourceTrigger=PropertyChanged}" ></TextBox>
    <Button Grid.Row="1" Grid.Column="0"  Content="Load"  Command="{Binding BtnLoad,UpdateSourceTrigger=PropertyChanged}"></Button>
    <Button Grid.Row="1" Grid.Column="1"  Content="Confirm" Command="{Binding BtnConfirm}"></Button>
    <Button Grid.Row="1" Grid.Column="2"  Content="Add" Command="{Binding BtnAdd,UpdateSourceTrigger=PropertyChanged}"></Button>
</Grid>


    public MainViewModel(ILogRepository logRepository)
    {

        _logRepository = logRepository;

        _listOfLogs = new List<Log>();
        BtnAdd = new BtnAdd(AddLog);
        BtnConfirm = new BtnConfirm(ConfimLog, LogIsSelected);
        BtnLoad = new BtnLoad(LoadLogTable);

    }
    private bool LogIsSelected()
    {
        // return true;
        //Funktionerit im WPF nicht
        if (_selectedLogItem != null)
            return true;
        return false;
    }


【问题讨论】:

  • 欢迎来到 Stack Overflow。您似乎遇到了一些您没有向我们展示的代码的问题。请通过编辑您的问题并将代码添加到您的问题中向我们展示该代码。当命令的执行能力发生变化时,您可能需要引发命令的CanExecuteChanged 事件。如果你不这样做,按钮就不会知道它需要再次调用 CanExecute。
  • 您可以从这些绑定中删除UpdateSourceTrigger=PropertyChanged。 Command 属性永远不会创建新的 Command 对象并将其分配回您的 viewmodel 属性,因此无需确切告诉它何时执行此操作。即使它愿意尝试,您的属性也可能是只读的。
  • 澄清一下:您没有向我们展示的代码是命令本身。是什么决定了它能否执行?
  • Logisselected 是私有的。我认为它需要公开才能使视图获得任何价值。您还需要一些用户 ui 交互或docs.microsoft.com/en-us/dotnet/api/…,然后才能对其进行检查。

标签: c# wpf mvvm


【解决方案1】:

这是一个示例,向您展示了 can-execute 方法的工作原理。当连接字符串输入字段中有文本时,确认按钮变为启用状态。它与您的代码不完全一样,但您指的是我在您的 XAML 中没有看到的列表。

MainWindow.xaml(后面的代码中没有)

<Window x:Class="FrameworkCanExecuteExample.MainWindow"
        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:FrameworkCanExecuteExample"
        mc:Ignorable="d"
        Title="MainWindow"
        Width="300"
        Height="100">

    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <TextBlock Text="Connection string:" />
        <TextBox Grid.Column="1" Text="{Binding Path=ConnectionString, UpdateSourceTrigger=PropertyChanged}" />

        <Button Grid.Row="1" Grid.ColumnSpan="2"  Content="Confirm"  Command="{Binding BtnConfirm}" />
    </Grid>
</Window>

MainViewModel.cs

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace FrameworkCanExecuteExample
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private string connectionString;

        public event PropertyChangedEventHandler PropertyChanged;

        public MainViewModel()
        {
            BtnConfirm = new RelayCommand(Confirm, CanConfirm);
        }

        public string ConnectionString
        {
            get => connectionString;
            set
            {
                connectionString = value;
                OnPropertyChanged();
            }
        }

        public ICommand BtnConfirm { get; }


        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void Confirm(object parameter)
        {
        }

        private bool CanConfirm(object parameter)
        {
            return !string.IsNullOrWhiteSpace(connectionString);
        }
    }
}

RelayCommand.cs

using System;
using System.Windows.Input;

namespace FrameworkCanExecuteExample
{
    public class RelayCommand : ICommand
    {
        private Action<object> execute;
        private Func<object, bool> canExecute;

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
        {
            this.execute = execute;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return canExecute == null || canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            execute(parameter);
        }
    }
}

【讨论】:

    猜你喜欢
    • 2013-10-28
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 2019-05-20
    相关资源
    最近更新 更多