9

私のプロジェクトは MVVM パターンに基づいています。

ファイル システムを表示するツリー ビューを作成しました。各フォルダには、現在のフォルダを選択するためのチェックボックスがあります。選択プロセスには時間がかかるため、操作の実行中に無効になっているボタンがあり、操作の最後にボタンを有効にしています。

私の問題は、ボタンが「無効」になるとすぐに表示されることです。ただし、ボタンが有効モードに戻るときは、ボタンが有効になっていることを確認するために何らかの操作 (マウス クリックなど) を行う必要があります。

ボタンが有効になった直後に UI が更新されるようにするにはどうすればよいですか?

これらは私のボタンです:

<Button Content="&lt;- Back" Margin="5,0,5,0" Width="80" Height="25"
        IsEnabled="{Binding CanMoveToPreviousPage, UpdateSourceTrigger=PropertyChanged}" 
        Command="{Binding Path=NavigateBackCommand, IsAsync=True}" />

<Button Content="{Binding ButtonNextCaption}" Margin="5,0,5,0" Width="80" Height="25"
        IsEnabled="{Binding CanMoveToNextPage, UpdateSourceTrigger=PropertyChanged}" 
        Command="{Binding Path=NavigateNextCommand, IsAsync=True}" />

ViewModelに次のコードを追加しました。

public bool CanMoveToNextPage
{
    get
    {
        return this.CurrentPage != null && this.CurrentPage.CanMoveNext;
    }
    set
    {
        if (CurrentPage != null)
        {
            this.CurrentPage.CanMoveNext = value;
            OnPropertyChanged("CanMoveToNextPage");
        }
    }
}

public bool CanMoveToPreviousPage
{
    get { return 0 < this.CurrentPageIndex && CurrentPage.CanMoveBack; }
    set
    {
        if (CurrentPage != null)
        {
            this.CurrentPage.CanMoveBack = value;
            OnPropertyChanged("CanMoveToPreviousPage");
        }
    }
}

UI の更新は、マウス クリックまたはキーストロークを実行した直後に行われます。

これは、ボタンを無効および有効にするアクションのコードです。

void bg_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
    DecrementDoneCounter();
    if (ThreadSafeCouner == 0)//means all bg workers are done
    {
        UIlimitation(true);
    }
}

private int ThreadSafeCouner; // check how many bgworkers run
public void IncrementDoneCounter() { Interlocked.Increment(ref ThreadSafeCouner); }
public void DecrementDoneCounter() { Interlocked.Decrement(ref ThreadSafeCouner); }


void bg_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    IncrementDoneCounter();
    UIlimitation(false);
    ((bgArguments)e.Argument).SelectedDirectory.CanSelected = false;
    MarkItems(((bgArguments)e.Argument).SelectedDirectory, ((bgArguments)e.Argument).IsSelect);
    ((bgArguments)e.Argument).FreeWorkerAllocation();
    ((bgArguments)e.Argument).SelectedDirectory.CanSelected = true;
}

//this is the enabling action which execute the propeties setters at the upper part of this post
private static void UIlimitation(bool limit)
{
    MainWindowViewModel.Instance.CanMoveToNextPage = limit;
    MainWindowViewModel.Instance.CanMoveToPreviousPage = limit;
}

私に何ができる?

4

3 に答える 3

6

あなたはあなたのコントロールを調整し Binding mode TwoWay、定義することができますtriggers with PropertyChanged

{Binding ElementName=.., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
于 2012-10-02T13:48:45.287 に答える
4

OK解決策を見つけました。
私は成功せずにすべてを試しましたが、最終的にこのスレッドを見つけました: Refresh WPF Command

利用したCommandManager.InvalidateRequerySuggested()

そしてその作品。

ご協力いただきありがとうございます

于 2012-10-03T05:58:33.793 に答える
2

UIを更新するためにメッセージを送信するINotifyPropertyChangedメソッドを使用してViewModelを設定する方法のコード例を次に示します。

public class MyViewModel : INotifyPropertyChanged
{
    /******************************************************/
    /* Property that you have created two-way binding for */
    /******************************************************/
    private double _myProperty
    public double MyProperty
    {
        get { return _myProperty; }
        set
        {
            _myProperty = value;

            OnNotifyPropertyChanged("MyProperty");
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnNotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChanged Members
}
于 2012-10-02T14:41:19.537 に答える