来自viewmodel的Visiblity无法正常工作

1 c# wpf mvvm mvvm-light

我有一个带登录视图模型的登录视图,遇到了一个让我疯狂的问题.请注意,我正在使用MVVM Light.

在viewmodel中,我有三个可见性属性,应根据viewmodel的状态隐藏视图中的元素.

我的属性看起来像这样,都触发了PropertyChangedEvent:

public Visibility ErrorPanelVisibility
public Visibility LoginPanelVisibility
public Visibility LoadingPanelVisibility
Run Code Online (Sandbox Code Playgroud)

绑定看起来像这样(省略边距等):

<Border Visibility="{Binding ErrorPanelVisibility}">
<StackPanel Visibility="{Binding LoginPanelVisibility}">
<StackPanel Visibility="{Binding LoadingPanelVisibility}">
Run Code Online (Sandbox Code Playgroud)

当用户按下登录按钮时,在viewmodel中执行此方法的命令会更改可见性:

private void ExecuteLogin()
{
    ErrorPanelVisibility = Visibility.Collapsed;
    LoginPanelVisibility = Visibility.Collapsed;
    LoadingPanelVisibility = Visibility.Visible;

    // This method takes a few seconds to complete.
    Login(errorMessage =>
            {
                if (!String.IsNullOrEmpty(errorMessage))
                {
                    ErrorMessage = errorMessage;

                    ErrorPanelVisibility = Visibility.Visible;
                    LoginPanelVisibility = Visibility.Visible;
                    LoadingPanelVisibility = Visibility.Collapsed;
                }
                else
                {
                    DialogResult = true;
                }
            });
}
Run Code Online (Sandbox Code Playgroud)

问题是面板没有折叠或在视图中更改为可见,更改不会反映在视图中.当我将可见性设置为Visible但不是Collapsed时,会触发PropertyChangedEvent并且ErrorPanel正在工作.

编辑:登录方法:

private void Login(Action<string> callback)
{           
    string errorMessage = string.Empty;

    if (SelectedServer == null)
    {
        errorMessage = "Select server."; //TODO: Translate
    }
    else if (String.IsNullOrEmpty(Username) || String.IsNullOrEmpty(Password))
    {
        errorMessage = Resources.WrongUsernameOrPassword;
    }
    else
    {
        try
        {
            // Changed name due to customer information
            IWCFClient wcfClient = WCFClient.GetInstance(); 

            LoginObj loginObj = wcfClient.Login(Username, Password);

            // Removed some cases to simplify, they all set the errorMessage.
            switch (loginObj.LoginStatus)
            {
                case LoginObj.LoginState.AlreadyLogedin:
                    errorMessage = Resources.UserAlreadyLoggedOn;
                    break;
                default:
                    errorMessage = Resources.ErrorOccurred;
                    break;    
            }                
        }
        catch (Exception e)
        {
            errorMessage = e.Message;
        }
    }
    callback(errorMessage);
}
Run Code Online (Sandbox Code Playgroud)

不过,面板做的工作,如果我我的代码改成这样:

bool login = false;
private void ExecuteLogin()
{
    if (login)
    {
        ErrorPanelVisibility = Visibility.Collapsed;
        LoginPanelVisibility = Visibility.Collapsed;
        LoadingPanelVisibility = Visibility.Visible;
    }
    else
    {
        ErrorPanelVisibility = Visibility.Visible;
        LoginPanelVisibility = Visibility.Visible;
        LoadingPanelVisibility = Visibility.Collapsed;
    }

    login = !login;
}
Run Code Online (Sandbox Code Playgroud)

这里有没有明显的错误,或者有人能发现我做错了吗?

Dzm*_*voi 5

也.我建议你在ViewModels中避免使用UI类型.尝试使用bool值并使用BoolToVisibilityConverter.

PS确保为控件设置DataContext.

  • +1以避免VM中的UI类型违反MVVM (2认同)