我只能使用依赖属性来使其工作,这有效地绕过了Caliburn.Micro提供的约定绑定优点。我知道这不是理想的解决方案,但从实用角度出发,这是我经常使用的解决方案。我相信在历史上遇到这个问题时,我在StackOverflow上找到了这篇文章,它引导我朝着这个方向前进。供参考:
public class BoundPasswordBox
{
private static bool _updating = false;
public static readonly DependencyProperty BoundPasswordProperty =
DependencyProperty.RegisterAttached("BoundPassword",
typeof(string),
typeof(BoundPasswordBox),
new FrameworkPropertyMetadata(string.Empty, OnBoundPasswordChanged));
public static string GetBoundPassword(DependencyObject d)
{
return (string)d.GetValue(BoundPasswordProperty);
}
public static void SetBoundPassword(DependencyObject d, string value)
{
d.SetValue(BoundPasswordProperty, value);
}
private static void OnBoundPasswordChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
PasswordBox password = d as PasswordBox;
if (password != null)
{
password.PasswordChanged -= PasswordChanged;
}
if (e.NewValue != null)
{
if (!_updating)
{
password.Password = e.NewValue.ToString();
}
}
else
{
password.Password = string.Empty;
}
password.PasswordChanged += PasswordChanged;
}
static void PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox password = sender as PasswordBox;
_updating = true;
SetBoundPassword(password, password.Password);
_updating = false;
}
}
然后,在你的XAML中:
<PasswordBox pwbx:BoundPasswordBox.BoundPassword="{Binding UserPassword, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,NotifyOnValidationError=True,ValidatesOnDataErrors=True}" />
在 Window 标签上发现了 pwbx 作为命名空间:
<Window x:Class="MyProject.Views.LoginView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:pwbx="clr-namespace:MyProject.Client.Controls">
视图模型(ViewModel):
using Caliburn.Micro;
using MyProject.Core;
using MyProject.Repositories;
using MyProject.Types;
using MyProject.ViewModels.Interfaces;
namespace MyProject.ViewModels
{
public class LoginViewModel : Screen, ILoginViewModel
{
private readonly IWindowManager _windowManager;
private readonly IUnitRepository _unitRepository;
public bool IsLoginValid { get; set; }
public Unit LoggedInUnit { get; set; }
private string _password;
public string UserPassword
{
get { return _password; }
set
{
_password = value;
NotifyOfPropertyChange(() => UserPassword);
NotifyOfPropertyChange(() => CanLogin);
}
}
private string _name;
public string Username
{
get { return _name; }
set
{
_name = value;
NotifyOfPropertyChange(() => Username);
NotifyOfPropertyChange(() => CanLogin);
}
}
public LoginViewModel(IWindowManager windowManager,IUnitRepository unitRepository)
{
_windowManager = windowManager;
_unitRepository = unitRepository;
DisplayName = "MyProject - Login";
Version = ApplicationVersionRepository.GetVersion();
}
public string Version { get; private set; }
public void Login()
{
var credentials = new UserCredentials { Username = Username, Password=UserPassword };
var resp = _unitRepository.AuthenticateUnit(credentials);
if (resp == null) return;
if (resp.IsValid)
{
IsLoginValid = true;
LoggedInUnit = resp.Unit;
TryClose();
}
else
{
var dialog = new MessageBoxViewModel(DialogType.Warning, DialogButton.Ok, "Login Failed", "Login Error: " + resp.InvalidReason);
_windowManager.ShowDialog(dialog);
}
}
public bool CanLogin
{
get
{
return !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(UserPassword);
}
}
}
}
PasswordChanged
方法的末尾添加这个:https://dev59.com/rEfSa4cB1Zd3GeqPBv3F#1046920。 - thomasb""
,则该助手将永远不会被调用,用户输入或更改密码时也不会更新vm的属性。这是因为FrameworkPropertyMetadata
的默认值设置为string.Empty
。将其设置为null
即可在这种情况下正常工作。 - ssarabando