【问题标题】:Binding Command Parameter to ViewModel Property [duplicate]将命令参数绑定到 ViewModel 属性 [重复]
【发布时间】:2021-05-12 00:46:05
【问题描述】:

WPF 和 MVVM 的全新功能。我的应用程序有一个用于浏览文件的按钮和一个用于对所选文件执行任务的开始按钮。如果用户使用浏览按钮选择了文件,我只希望用户可以使用开始按钮。我使用 ViewModel 中的文件路径属性作为 CommandParameter 但这不起作用。任何帮助表示赞赏。

XAML

<Button Grid.Column="1" Grid.Row="2" Content="Browse File" Margin="0,0,5,5" Command="{Binding Path=CommandBrowseFile}" ></Button> 
    <Button Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="2" Content="Start" Margin="0,0,0,5" Command="{Binding Path=CommandStart}" CommandParameter="{Binding Path=FilePath}"></Button>

视图模型

public class MyViewModel : ViewModelBase
{
    public RelayCommand CommandBrowseFile { get; private set; }
    public RelayCommand CommandStart { get; private set; }
    private string _filePath;

    public MyViewModel()
    {
        //L5XPath = "test";
        CommandBrowseFile = new RelayCommand(BrowseFile);
        CommandStart = new RelayCommand(Start, CanStart);
        
    }

    public string FilePath
    {
        get { return _filePath; }
        set
        {
            _filePath = value;
        }
    }

    public void BrowseFile(object message)
    {
        // Configure open file dialog box
        OpenFileDialog dlg = new OpenFileDialog();
        dlg.FileName = "Document"; // Default file name
        dlg.DefaultExt = ".l5x"; // Default file extension
        dlg.Filter = "l5x files (.l5x)|*.l5x"; // Filter files by extension

        // Show open file dialog box
        Nullable<bool> result = dlg.ShowDialog();

        // Process open file dialog box results

        FilePath = result == true ? dlg.FileName : null;
    }

    public void Start(object message)
    {
        //Do something
    }

    public bool CanStart(object message)
    {
        return message != null ? true : false;
    }
}

中继命令

public class RelayCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

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

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
        {
            throw new NullReferenceException("execute");
        }

        else
        {
            _execute = execute;
            _canExecute = canExecute;
        }            
    }

    //public void RaiseCanExecuteChanged()
    //{
    //    if (CanExecuteChanged != null)
    //        CanExecuteChanged(this, new EventArgs());
    //}

    public RelayCommand(Action<object> execute) : this(execute, null)
    {

    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute.Invoke(parameter);
    }
}

【问题讨论】:

  • 您没有正确实现绑定。查看重复项。

标签: c# wpf data-binding


【解决方案1】:

我会修改CanStart 方法并在FilePath 的setter 中调用OnPropertyChanged()

public bool CanStart(object message)
{
    return !string.IsNullOrEmpty(FilePath);
}

public string FilePath
{
    get { return _filePath; }
    set
    {
        _filePath = value;
       OnPropertyChanged(); // method in your ViewModelBase
       CommandStart.RaiseCanExecuteChanged();
    }
}

还取消注释RaiseCanExecuteChanged 并在FilePath 更新时在CommandStart 命令上调用此方法,以通知UI 该命令是否已启用。

public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
    if (CanExecuteChanged != null)
        CanExecuteChanged(this, new EventArgs());
}

【讨论】:

  • 为什么我的开始按钮的命令参数即使绑定属性不为空也总是为空?
  • @James 正在尝试复制并且工作正常。您在输出窗口中看到任何绑定错误吗?
  • 我的 XAML 绑定失败输出中没有显示任何内容
  • XAML 绑定失败窗口中没有错误。您的解决方案有效,我只是希望了解为什么我的解决方案无效。
【解决方案2】:

你还没有使用过CommandStart.RaiseCanExecuteChanged();,并且这个命令调用了CanStart()函数,你必须检查_filePath的值是否为空

public string FilePath
{
     get { return _filePath; }
     set
     {
         _filePath = value;
         CommandStart.RaiseCanExecuteChanged();
     }
}
        
public bool CanStart(object message)
{
    return _filePath != null ? true : false;
}

在中继命令中

public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
    if (CanExecuteChanged != null)
        CanExecuteChanged(this, EventArgs.Empty);
}

【讨论】:

  • 谢谢,您的解决方案有效,但我想了解为什么我的解决方案无效。
  • 我不明白这行 CommandManager.RequerySuggested 所以我使用了自己的代码并在答案中添加了描述
【解决方案3】:

您必须在命令参数中使用的属性上调用 PropertyChanged 事件。

public string FilePath
    {
        get { return _filePath; }
        set
        {
            _filePath = value;
            NotifyPropertyChanged("FilePath");
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 2013-10-09
    • 1970-01-01
    • 2012-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多