4

いくつかの条件が真でない限り、アプリケーションは特定のメニュー項目にアクセスできません (DataRepository.IsAllDataLoaded)。私はこのコードを思いつきました。これはうまく機能します。最初に状態をチェックします。準備ができていない場合は、数ミリ秒待機してから同じメソッドを再度呼び出すタイマーを呼び出します。タイマーには ElapsedEventHandler が必要です。

public void FirstMenuItem_Click(object sender, RoutedEventArgs e)
{
  if (!DataRepository.IsAllDataLoaded)
  {
    WaitForDataLoading(FirstTimedEvent);        
  }
  else
  {        
    Dispatcher.BeginInvoke(new Action(() =>
   {
     IndividualEntryWindow Window = new IndividualEntryWindow();
     Window.Show();
   }));
  }
}
private void FirstTimedEvent(object source, ElapsedEventArgs e)
{
  FirstMenuItem_Click(null, null);
}

private static void WaitForDataLoading(ElapsedEventHandler timerEvent)
{
  Timer t = new Timer();
  t.Interval = 0.2;
  t.AutoReset = false; 
  t.Elapsed += new ElapsedEventHandler(timerEvent);
  t.Start();
}

当初は、FirstMenuItem_Clickが唯一の方法でした。FirstTimedEventタイマーのハンドラーを追加する必要がありました。それを作成しないようにする方法はありElapsedEventHandlerますか? FirstMenuItem_Clickメソッドでインラインで作成できますか?

他の多くの Item_Click メソッドにも同じパターンを使用する必要があります。ElapsedEventHandler各 Item_Click メソッドを作成する必要がないことを願っています。

4

3 に答える 3

2

匿名ラムダ式を使用します。

WaitForDataLoading((s,e) => FirstMenuItem_Click(null, null));
于 2013-05-23T12:47:10.650 に答える
0

次のコードではCheckDataShowWindow()、データの準備ができたときにウィンドウを表示したいときにいつでもメソッドを呼び出すことができます。別の cick ハンドラーに追加したい場合は、次のように別のものを作成できます。

public void Another_Click(object sender, RoutedEventArgs e)
{
    CheckDataShowWindow();
}

メインコード:

public void FirstMenuItem_Click(object sender, RoutedEventArgs e)
{
    CheckDataShowWindow();
}

private void CheckDataShowWindow()
{
    if (!DataRepository.IsAllDataLoaded)
    {
        Timer t = new Timer();
        t.Interval = 0.2;
        t.AutoReset = false; 
        t.Elapsed += (s,e) => CheckDataShowWindow();
        t.Start();
    }
    else
    {
        Dispatcher.BeginInvoke(new Action(() =>
        {
            IndividualEntryWindow Window = new IndividualEntryWindow();
            Window.Show();
        }));
    }
}

アップデート

データリポジトリのコードを編集できる場合は、データの読み込みが完了したときのイベントを追加する必要があります。

public delegate void DoneLoadingHandler(object sender, EventArgs e);
public class DataRepository
{
    public event DoneLoadingHandler DoneLoading;
    //Your loading function
    private void LoadAllData()
    {
        //Load like you do now

        //Now fire the event that loading is done.
        if(DoneLoading != null)
            DoneLoading(this, new EventArgs());
    }
}

今あなたの他のクラスで:

public void FirstMenuItem_Click(object sender, RoutedEventArgs e)
{
    CheckDataShowWindow();
}

private bool AllReadyWaiting = false;
private void CheckDataShowWindow()
{
    if (!DataRepository.IsAllDataLoaded)
    {
        if(!AllReadyWaiting)
        {
            DataRepository.DoneLoading += (s,e) => ShowWindow();
            AllReadyWaiting = true;
        }
    }
    else
    {
        ShowWindow();
    }
}

private void ShowWindow()
{
    Dispatcher.BeginInvoke(new Action(() =>
    {
        IndividualEntryWindow Window = new IndividualEntryWindow();
        Window.Show();
    }));
}
于 2013-05-23T12:43:34.207 に答える
0

Dispatcherクラスの使用に基づいて、WPFを使用しているようです。その場合、UI へのアクセスを制御するためのより適切な手段があります。

これらのうちの2つは次のとおりです。

  1. Enabledメニューのプロパティをクラスにバインドします。ViewModelこのクラスには、メニューを使用できるかどうかを示すプロパティがあります。長期実行ジョブが完了したら、プロパティを に設定するtrueと、メニューが有効になります。

  2. を使用しICommandて、メニューの動作を制御します。長時間実行ジョブがアクティブなときにコマンドがCanExecute戻るfalseと、ジョブが完了するまでメニューが自動的に無効になります。

これにより、メニューの動作が微妙に変更されることに注意してください。ただし、悪い意味ではないと思います。現在のコードは、ダイアログを表示する前にジョブが完了するのを待ちますが、その間にユーザーがメニューを再度クリックするのを止めるものは何もありません。これらの複数回のクリックは、それぞれジョブが完了するのを待ち、ジョブが完了するとそれぞれ独自のダイアログを表示します。些細なケースでは、これは複数のダイアログが表示されることを意味する場合があります。深刻なケースでは、作成している複数のタイマーがアプリケーションのパフォーマンスに悪影響を及ぼす可能性があります。

上記の方法のいずれかを使用すると、ジョブの実行中にメニューがクリックされなくなります。これは現在の動作ではありませんが、使いやすさの観点からはより理にかなっていると思います。

于 2013-05-23T12:52:49.210 に答える