.net 使用ReactiveUI与PasswordBox进行双向绑定
我遇到了一个问题,如何在.net 使用ReactiveUI与PasswordBox进行双向绑定,.net,wpf,xaml,reactiveui,.net,Wpf,Xaml,Reactiveui,我遇到了一个问题,如何在PasswordBox中以双向方式正确绑定密码。我目前的解决方案几乎奏效。它的问题是,在键入过程中,光标停留在开头,而不是跟文本在结尾。键入12345,我的视图模型接收值54321 我正在使用WFP和XAML。视图背后的代码如下所示: Observable.FromEventPattern(SecretKey, nameof(SecretKey.PasswordChanged)) .Subscribe(evt => ViewModel.SecretKey =
PasswordBox
中以双向方式正确绑定密码。我目前的解决方案几乎奏效。它的问题是,在键入过程中,光标停留在开头,而不是跟文本在结尾。键入12345
,我的视图模型接收值54321
我正在使用WFP和XAML。视图背后的代码如下所示:
Observable.FromEventPattern(SecretKey, nameof(SecretKey.PasswordChanged))
.Subscribe(evt => ViewModel.SecretKey = SecretKey.Password)
.DisposeWith(disposableRegistration);
this.OneWayBind(ViewModel, viewModel => viewModel.SecretKey, view => view.SecretKey.Password)
.DisposeWith(disposableRegistration);
当其中一个结构被注释时,游标的行为是正确的,所以问题在于以两种方式绑定,我不知道如何解决它。正如您现在所看到的那样,PasswordBox.Password不能从视图绑定到视图模型,我需要使用事件。我认为没有“官方”的方法,我不确定您是否应该这样做。
但您可以在设置值后手动设置光标位置以解决此问题() “黑客”绑定:
this.WhenAnyValue(x => x.ViewModel.SecretKey)
.Where(pw => pw != null)
.Do(pw =>
{
secretKey.Password = pw;
SetCursor(secretKey, pw.Length);
})
.Subscribe()
.DisposeWith(disposableRegistration);
PasswordBox
通常由附加属性处理。我做了研究,ReactiveUi
binding不能处理带有附加属性的双向绑定。另一方面,当您使用ReactiveUi
时,XAML中的绑定没有危险信号-这是不鼓励的,但不是禁止的。请记住,纯ReactiveUi
无法实现附加属性,我决定在绑定密码箱时破例,我认为这是合理和正确的
我使用了PasswordHelper
,它实现了上教程中的附加属性
在XAML中,我使用带有附加属性的密码箱的标准绑定:
<PasswordBox Name="PasswordBox"
local:PasswordHelper.Attach="True"
local:PasswordHelper.Password="{Binding Password, Mode=TwoWay}"/>
您可以在中找到示例应用程序
public static class PasswordHelper
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.RegisterAttached("Password",
typeof(string), typeof(PasswordHelper),
new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
public static readonly DependencyProperty AttachProperty =
DependencyProperty.RegisterAttached("Attach",
typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false, Attach));
private static readonly DependencyProperty IsUpdatingProperty =
DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
typeof(PasswordHelper));
public static void SetAttach(DependencyObject dp, bool value)
{
dp.SetValue(AttachProperty, value);
}
public static bool GetAttach(DependencyObject dp)
{
return (bool)dp.GetValue(AttachProperty);
}
public static string GetPassword(DependencyObject dp)
{
return (string)dp.GetValue(PasswordProperty);
}
public static void SetPassword(DependencyObject dp, string value)
{
dp.SetValue(PasswordProperty, value);
}
private static bool GetIsUpdating(DependencyObject dp)
{
return (bool)dp.GetValue(IsUpdatingProperty);
}
private static void SetIsUpdating(DependencyObject dp, bool value)
{
dp.SetValue(IsUpdatingProperty, value);
}
private static void OnPasswordPropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
passwordBox.PasswordChanged -= PasswordChanged;
if (!(bool)GetIsUpdating(passwordBox))
{
passwordBox.Password = (string)e.NewValue;
}
passwordBox.PasswordChanged += PasswordChanged;
}
private static void Attach(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
if (passwordBox == null)
return;
if ((bool)e.OldValue)
{
passwordBox.PasswordChanged -= PasswordChanged;
}
if ((bool)e.NewValue)
{
passwordBox.PasswordChanged += PasswordChanged;
}
}
private static void PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
SetIsUpdating(passwordBox, true);
SetPassword(passwordBox, passwordBox.Password);
SetIsUpdating(passwordBox, false);
}
}
<PasswordBox Name="PasswordBox"
local:PasswordHelper.Attach="True"
local:PasswordHelper.Password="{Binding Password, Mode=TwoWay}"/>
this.WhenActivated(d =>
{
this.WhenAnyValue(x => x.ViewModel).BindTo(this, x => x.DataContext).DisposeWith(d);
});