1

ログインビューモデルを使用したログインビューがあり、気が狂うような問題に遭遇しました。MVVM Light を使用していることに注意してください。

ビューモデルには、ビューモデルの状態に応じてビュー内の要素を非表示にする 3 つの可視性プロパティがあります。

私のプロパティは次のようになり、すべてが PropertyChangedEvent をトリガーします。

public Visibility ErrorPanelVisibility
public Visibility LoginPanelVisibility
public Visibility LoadingPanelVisibility

バインディングは次のようになります (マージンなどを省略):

<Border Visibility="{Binding ErrorPanelVisibility}">
<StackPanel Visibility="{Binding LoginPanelVisibility}">
<StackPanel Visibility="{Binding LoadingPanelVisibility}">

ユーザーがログイン ボタンを押すと、ビューモデルでこのメソッドを実行するコマンドによって可視性が変更されます。

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;
                }
            });
}

問題は、パネルが折りたたまれていないか、ビューに表示されるように変更されておらず、変更がビューに反映されていないことです。可視性を 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);
}

ただし、コードを次のように変更すると、パネルは機能します。

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;
}

ここで明らかな間違いがありますか、それとも私が間違っていることを誰かが見つけることができますか?

4

3 に答える 3

5

また。ViewModel では UI タイプを避けることをお勧めします。ブール値を使用して、BoolToVisibilityConverter を使用してみてください。

PSコントロールのDataContextを必ずセットアップしてください。

于 2012-10-17T08:21:22.127 に答える
1

UI スレッドですべての作業を行っており、パネルが更新される機会がありません。UI の応答性を維持するには、BackgroundWorker を使用します。

http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

それはもっと似ているはずです:

1) UI バインディングに影響するいくつかのプロパティを変更します。

2) ワーカー スレッドを開始する

3) UI スレッドの制御を戻して更新できるようにする

4) UI バインディングに影響するいくつかのプロパティを変更して、ワーカー スレッドの終了に対応する

于 2012-10-17T09:35:45.797 に答える
0

1) Binding.Modeを見逃しました。したがって、 xaml バインディングに Mode を追加する必要があります (例: <Border Visibility="{Binding ErrorPanelVisibility, Mode=OneWay}">.

2) ViewModel はINotifyPropertyChange、それ自体から View に変更を発生させるために実装する必要があります。

public event PropertyChangedEventHandler PropertyChanged;

// Create the OnPropertyChanged method to raise the event 
protected void OnPropertyChanged(string name)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(name));
    }
}

public Visibility ErrorPanelVisibility 
{
    get { return this._errorPanelVisibility; }
    set
    {
        if (this._errorPanelVisibility == value)
        {
            return;
        }

        this._errorPanelVisibility = value;
        OnPropertyChanged("ErrorPanelVisibility");
    }
}

私も Dima Martovoi に同意します。View と ViewModel を混在させてはいけません。これには少なくとも 2 つの方法があります。最初の方法は、ビューからクリック イベントに関連するコードを移動するか、MessengerViewModelを使用して からにメッセージを送信できますView

于 2012-10-17T09:21:31.203 に答える