This question already has an answer here:
Binding to properties in both the ViewModel and CodeBehind

(1个答案)


在8个月前关闭。




单击 View 中的按钮时,我想传递ViewModel参数(类变量)。当指定一个字符串时,一切都变为现实,但是我需要从View类(函数 AddNewField )传递一个非字符串值。
Main.xaml :
...
<Button
    x:Name="ButtonAddingField"
    CommandParameter="{Binding Path=Myprop}"
    Command="{Binding Path=Myprop, RelativeSource={RelativeSource AncestorType=UserControl}}" />
...
Main.cs :
...
    private Color myprop;

    public Color Myprop
    {
        get => myprop;
    }


...
this.DataContext = new FieldCollectionViewModel(fields); // fields - List<*my Model*>

...
FieldCollectionViewModel.cs :
...
private DelegateCommand<object> addFieldCommand;

public ICommand AddFieldCommand {
    get {
        if (addFieldCommand == null) addFieldCommand = new DelegateCommand<object>(AddNewField);
        return addFieldCommand;
    }
}

private void AddNewField(object parameter)
{
    // !!! parameter = ALWAYS NULL
}
...
和我的 DelegateCommand.cs:
    ...
public class DelegateCommand<T> : ICommand
{
    #region Constructors

    /// <summary>
    ///     Constructor
    /// </summary>
    public DelegateCommand(Action<T> executeMethod)
        : this(executeMethod, null, false)
    {
    }

    /// <summary>
    ///     Constructor
    /// </summary>
    public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
        : this(executeMethod, canExecuteMethod, false)
    {
    }

    /// <summary>
    ///     Constructor
    /// </summary>
    public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
    {
        if (executeMethod == null) throw new ArgumentNullException("executeMethod");

        _executeMethod = executeMethod;
        _canExecuteMethod = canExecuteMethod;
        _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
    }

    #endregion Constructors

    #region Public Methods

    /// <summary>
    ///     Method to determine if the command can be executed
    /// </summary>
    public bool CanExecute(T parameter)
    {
        if (_canExecuteMethod != null) return _canExecuteMethod(parameter);
        return true;
    }

    /// <summary>
    ///     Execution of the command
    /// </summary>
    public void Execute(T parameter)
    {
        if (_executeMethod != null) _executeMethod(parameter);
    }

    /// <summary>
    ///     Raises the CanExecuteChaged event
    /// </summary>
    public void RaiseCanExecuteChanged()
    {
        OnCanExecuteChanged();
    }

    /// <summary>
    ///     Protected virtual method to raise CanExecuteChanged event
    /// </summary>
    protected virtual void OnCanExecuteChanged()
    {
        CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
    }

    /// <summary>
    ///     Property to enable or disable CommandManager's automatic requery on this command
    /// </summary>
    public bool IsAutomaticRequeryDisabled {
        get => _isAutomaticRequeryDisabled;
        set {
            if (_isAutomaticRequeryDisabled != value)
            {
                if (value)
                    CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
                else
                    CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
                _isAutomaticRequeryDisabled = value;
            }
        }
    }

    #endregion Public Methods

    #region ICommand Members

    /// <summary>
    ///     ICommand.CanExecuteChanged implementation
    /// </summary>
    public event EventHandler CanExecuteChanged {
        add {
            if (!_isAutomaticRequeryDisabled) CommandManager.RequerySuggested += value;
            CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
        }
        remove {
            if (!_isAutomaticRequeryDisabled) CommandManager.RequerySuggested -= value;
            CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
        }
    }

    bool ICommand.CanExecute(object parameter)
    {
        // if T is of value type and the parameter is not
        // set yet, then return false if CanExecute delegate
        // exists, else return true
        if (parameter == null &&
            typeof(T).IsValueType)
            return _canExecuteMethod == null;
        return CanExecute((T)parameter);
    }

    void ICommand.Execute(object parameter)
    {
        Execute((T)parameter);
    }

    #endregion ICommand Members

    #region Data

    private readonly Action<T> _executeMethod;
    private readonly Func<T, bool> _canExecuteMethod;
    private bool _isAutomaticRequeryDisabled;
    private List<WeakReference> _canExecuteChangedHandlers;

    #endregion Data
}
...
我该如何解决我的问题?
更新
我更改了代码,现在可以正常工作了
感谢 @ mm8

最佳答案

Myprop必须是DataContextButton的公共(public)属性,以便您当前的绑定(bind)起作用。
如果它是父UserControl的属性,则可以使用RelativeSource绑定(bind)到它:

CommandParameter="{Binding Path=Myprop, RelativeSource={RelativeSource AncestorType=UserControl}}"
请注意,您只能绑定(bind)到公共(public)属性。您无法绑定(bind)到字段。

关于c# - 在MVVM中使用CommandParameter传递类变量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62537823/

10-12 02:48
查看更多