从ViewModel到View

时间:2015-07-30 19:46:58

标签: c# wpf mvvm

我需要验证两个密码字段。如果它们匹配,则必须在验证视图模型中验证凭证。我在验证视图模型中设置了bool值validPassword,需要在视图中引用它。然后根据validPassword值在视图中执行某些操作。但是,当我在视图中引用validPassword时,validPassword始终为false,即使在viewmodel中为true也是如此。

视图模型:

 internal static bool validPassword;
    public static bool CheckCredentials(string username, string password, string domain)
    {
        string userPrincipalName = username + "@" + domain + ".com";


        try
        {
            using(var context = new PrincipalContext(ContextType.Domain, domain))
            {
                validPassword = true;
                return context.ValidateCredentials(userPrincipalName, password);
            }
        }
        catch // a bogus domain causes an LDAP error
        {
            errorsForPassword.Add("Invalid Login!");
            validPassword = false;
            return false;
        }
    }

视图背后的代码:

  private void PwBox_OnKeyDown(object sender, RoutedEventArgs e)
    {
        System.Windows.Controls.ToolTip toolTip = new System.Windows.Controls.ToolTip();
        //PasswordBox passwordBox = sender as PasswordBox;
        passwordAgain = PasswordAgainBox.Password;
        if(string.IsNullOrEmpty(passwordAgain) || !string.Equals(passwordAgain, MiscParameterViewModel.password))
        {
            PwBoxBorder.BorderBrush = new SolidColorBrush(Colors.Red);                
            MiscParameterViewModel.nextButtonIsEnabled = false;
            if(string.IsNullOrEmpty(passwordAgain))
            {
                toolTip.Content = "Please enter the password again!";
                ToolTipService.SetToolTip(PasswordAgainBox, toolTip);
            }
            else if(!string.Equals(passwordAgain, MiscParameterViewModel.password))
            {
                toolTip.Content = "Passwords don't match!";
                ToolTipService.SetToolTip(PasswordAgainBox, toolTip);
            }
        } 
        else
        {
            //ToolTipService.SetToolTip(PasswordAgainBox, null);
            //PwBoxBorder.BorderBrush = new SolidColorBrush(Colors.Transparent);
            _validationViewModel.Authenticate();
            if(!ValidationViewModel.validPassword)
            {
                toolTip.Content = "Invalid password!";
                ToolTipService.SetToolTip(PasswordBox, toolTip);
                ToolTipService.SetToolTip(PasswordAgainBox, toolTip);
                PwBoxBorder.BorderBrush = new SolidColorBrush(Colors.Red);
                PwBoxAgainBorder.BorderBrush = new SolidColorBrush(Colors.Red);  
            }
            else
            {
                ToolTipService.SetToolTip(PasswordBox, null);
                ToolTipService.SetToolTip(PasswordAgainBox, null);
                PwBoxBorder.BorderBrush = new SolidColorBrush(Colors.Transparent);
                PwBoxAgainBorder.BorderBrush = new SolidColorBrush(Colors.Transparent);  
            }

        }
    }

Authenticate是viewmodel中的异步方法,它调用CheckCredentials方法。

以下是Authenticate方法:

  public async void Authenticate()
    {
        MiscParameterViewModel.nextButtonIsEnabled = false;
        NotifyPropertyChanged("NextButtonIsEnabled");
        const string propertyKey = "Password";            
        bool isValid = false;

        /* Call service asynchronously */
        if(MiscParameterViewModel.servServiceLoginType == ServiceLoginTypes.Windows)
        {
            if(errorKeys.ContainsKey(propertyKey))
            {
                errorsForPassword.Clear();
                errorKeys.TryRemove(propertyKey, out errorsForPassword);

                /* Raise event to tell WPF to execute the GetErrors method */
                RaiseErrorsChanged(propertyKey);
            }

            //if(string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(passwordAgain))
            if(string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
            {
                errorsForPassword.Add("Login is required!");
                errorKeys.TryAdd(propertyKey, errorsForPassword);

                isValid = false;
            }
            else
            {

                isValid = await Task<bool>.Run(() =>
                {
                    return CheckCredentials(username, password, domain);
                })
                .ConfigureAwait(false);
            }


        }

1 个答案:

答案 0 :(得分:1)

发生的事情是您的Authenticate方法正在另一个线程上执行CheckCredentials,然后将控制权返回给您的视图。这意味着你(有时)会走到这一行:

if(!ValidationViewModel.validPassword)

在调用CheckCredentials之前。您看到了错误,因为它是布尔值的默认值 - 它尚未设置。

您可以通过几种不同的方式解决此问题。您可以从authenticate方法返回一个Task,然后在检查validPassword之前调用该任务上的.Wait()。

或者你可以简单地从Authenticate方法中删除async / await并使其成为同步方法。哪个是正确的取决于你的应用程序的其余部分。

编辑:这是我对您的身份验证方法的尝试。我不得不猜测你想要的一些功能。

public async Task<bool> Authenticate()
{
    MiscParameterViewModel.nextButtonIsEnabled = false;
    NotifyPropertyChanged("NextButtonIsEnabled");
    const string propertyKey = "Password";

    /* Call service asynchronously */
    if(MiscParameterViewModel.servServiceLoginType == ServiceLoginTypes.Windows)
    {
        if(errorKeys.ContainsKey(propertyKey))
        {
            errorsForPassword.Clear();
            errorKeys.TryRemove(propertyKey, out errorsForPassword);

            /* Raise event to tell WPF to execute the GetErrors method */
            RaiseErrorsChanged(propertyKey);
        }

        //if(string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(passwordAgain))
        if(string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
        {
            errorsForPassword.Add("Login is required!");
            errorKeys.TryAdd(propertyKey, errorsForPassword);

            return false;
        }
        else
        {
            return await Task<bool>.Factory.StartNew(() => CheckCredentials(username, password, domain));
        }
    }
    return false;
}

一旦你完成任务,你就必须决定如何处理它。如果你只是打电话给.Wait(),它会起作用,但是当你等待时,你会遇到GUI冻结的问题。

您可能希望使用.ContinueWith()方法,该方法将在任务完成后调用,然后在那里您可以更新密码框。您可能需要将更改编组回GUI线程(ContinueWith将在另一个线程上)来设置密码框的值 - 如果没有完整的解决方案,则不确定。希望有所帮助