MVVM WPF Multibinding не работает для параметров команды - PullRequest
0 голосов
/ 08 января 2019

Я не могу заставить работать мультисвязывание для двух паролей. Я прочитал кучу статей в сети, попробовал рабочие примеры, но ни одна из них не была тем же сценарием, который я пробовал. Проблема заключается в том, что когда я нажимаю кнопку входа в систему, эти поля пароля не передаются в команду Execute method.

XAML для конвертера:

<Grid.Resources>
    <converter:PasswordConverter x:Key="passwordConverter"/>
</Grid.Resources>

XAML для кнопки выглядит так:

<Button x:Name="loginButton" 
                Content="Belépés" 
                Margin="494,430,0,0" 
                VerticalAlignment="Top" 
                FontSize="20" 
                RenderTransformOrigin="-2.624,8.99" 
                HorizontalAlignment="Left" 
                Width="172"
                Command="{Binding NavCommand}">
            <Button.CommandParameter>
                <MultiBinding Converter="{StaticResource passwordConverter}" Mode="TwoWay">
                    <Binding Path="Password" ElementName="userIDPasswordBox"/>
                    <Binding Path="Password" ElementName="leaderIDPasswordBox"/>
                </MultiBinding>
            </Button.CommandParameter>
        </Button>

Код конвертера пароля:

public class PasswordConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values.Clone();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Команда реле:

public class RelayCommand : ICommand
{

    Action _TargetExecuteMethod;
    Func<bool> _TargetCanExecuteMethod;

    public RelayCommand(Action executeMethod)
    {
        _TargetExecuteMethod = executeMethod;
    }

    public RelayCommand(Action executeMethod, Func<bool> canExecuteMethod)
    {
        _TargetExecuteMethod = executeMethod;
        _TargetCanExecuteMethod = canExecuteMethod;
    }

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged(this, EventArgs.Empty);
    }

    #region ICommand Members

    bool ICommand.CanExecute(object parameter)
    {

        if (_TargetCanExecuteMethod != null)
        {
            return _TargetCanExecuteMethod();
        }

        if (_TargetExecuteMethod != null)
        {
            return true;
        }

        return false;
    }

    public event EventHandler CanExecuteChanged = delegate { };

    void ICommand.Execute(object parameter)
    {
        if (_TargetExecuteMethod != null)
        {
            _TargetExecuteMethod();
        }
    }

    #endregion
}

и последний огромный кусок кода для модели представления:

public class LogonViewModel : BaseViewModel
{

private Action _loginActionComplete;
public LogonViewModel(Action loginActionComplete)
{
    _measureTimer = new Timer();
    _measureTimer.Interval = 500D;
    _measureTimer.Elapsed += measureTimer_Elapsed;
    _measureTimer.Start();
    _loginActionComplete = loginActionComplete;
    NavCommand = new RelayCommand(loginActionComplete);
    SerialPort = new SerailCommunicationNameSpace.SerialCommunication("COM3");
}

~LogonViewModel()
{
    SerialPort.Close();
}

public RelayCommand NavCommand { get; private set; }

private double _measuredWeight;
public double MeasuredWeight {
    get
    {
        return _measuredWeight;
    }
    set
    {
        SetProperty(ref _measuredWeight, value);
    }
}
private Timer _measureTimer;
public SerailCommunicationNameSpace.SerialCommunication SerialPort { get; set; }

private void measureTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    var measuredWeight = 0D;
    if (string.IsNullOrWhiteSpace(SerialPort.DataReceived) == false) {
        var dataReceivedStartTrim = SerialPort.DataReceived.TrimStart();
        var dataReceivedNumbersOnly = dataReceivedStartTrim.Substring(0, dataReceivedStartTrim.IndexOf(' '));
        var enUSCultureInfo = new CultureInfo("en-US");
        measuredWeight = double.Parse(dataReceivedNumbersOnly, enUSCultureInfo);
    }
    SetProperty(ref _measuredWeight, measuredWeight);
    OnPropertyChanged("MeasuredWeight");
}

public string LeaderId { get; set; }

public string UserId { get; set; }

}

1 Ответ

0 голосов
/ 08 января 2019

Проблема в том, что Password свойство PasswordBox не является ни свойством зависимости, ни реализует INotifyPropertyChanged. Это означает, что изменения пароля не будут применены к привязке.
Например. если вы добавите обработчик событий для PasswordChanged в PasswordBox и зададите пароль для свойства Tag, то вы можете выполнить привязку к Tag, и привязка будет работать.

<Button x:Name="loginButton" 
        Content="Belépés" 
        Margin="494,430,0,0" 
        VerticalAlignment="Top" 
        FontSize="20" 
        RenderTransformOrigin="-2.624,8.99" 
        HorizontalAlignment="Left" 
        Width="172"
        Command="{Binding NavCommand}">
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource passwordConverter}">
            <Binding Path="Tag" ElementName="userIDPasswordBox"/>
            <Binding Path="Tag" ElementName="leaderIDPasswordBox"/>
        </MultiBinding>
    </Button.CommandParameter>
</Button>

<PasswordBox Name="userIDPasswordBox" PasswordChanged="PasswordBox_PasswordChanged"/>
<PasswordBox Name="leaderIDPasswordBox" PasswordChanged="PasswordBox_PasswordChanged"/>

private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
    var pbx = sender as PasswordBox;
    if (pbx!=null)
    {
        pbx.Tag = pbx.Password;
    }
}

Конечно, чтобы избежать кода, лежащего в основе реализации, вы должны переместить обработчик событий в поведение.

...