MVVM WPF 多重绑定不适用于命令参数
MVVM WPF Multibinding is not working for command parameters
我无法为两个密码框设置多重绑定。我确实在网上阅读了很多尝试工作示例的文章,但其中 none 与我尝试过的场景相同。问题是当我点击登录按钮时,这些密码字段不会传输到命令执行方法。
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; }
}
问题是 PasswordBox
的 Password
属性 既不是依赖项 属性 也不是实现 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;
}
}
当然,要避免实现代码隐藏,您应该将事件处理程序移至行为。
我无法为两个密码框设置多重绑定。我确实在网上阅读了很多尝试工作示例的文章,但其中 none 与我尝试过的场景相同。问题是当我点击登录按钮时,这些密码字段不会传输到命令执行方法。
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; }
}
问题是 PasswordBox
的 Password
属性 既不是依赖项 属性 也不是实现 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;
}
}
当然,要避免实现代码隐藏,您应该将事件处理程序移至行为。