4

WPF アプリに添付プロパティがあります。

以下のコードはOnLoadイベント内にありますが、ハッキーな 500 ミリ秒の遅延を追加しない限り機能しません。

この遅延を回避し、ビジュアル ツリーがいつ読み込まれたかを検出する方法はありますか?

private static void FrameworkElement_Loaded(object sender, RoutedEventArgs e)
{
    // ... snip...
    Window window = GetParentWindow(dependencyObject);

    // Without this delay, changing properties does nothing.
    Task task = Task.Run(
        async () =>
        {
            {
                // Without this delay, changing properties does nothing.
                await Task.Delay(TimeSpan.FromMilliseconds(500));

                Application.Current.Dispatcher.Invoke(
                    () =>
                    {
                        // Set False >> True to trigger the dependency property.
                        window.Topmost = false;
                        window.Topmost = true;                                              
                    });
            }
        });
 }

更新 1

@Willからの回答によると、「ディスパッチャーを使用して適切な優先度を選択してください」。これは見事に機能します:

private static void FrameworkElement_Loaded(object sender, RoutedEventArgs e)
{
   // Wrap *everything* in a Dispatcher.Invoke with an appropriately
   // low priority, to defer until the visual tree has finished updating.
   Application.Current.Dispatcher.Invoke(
   async () =>
        {
            // This puts us to the back of the dispatcher queue.
            await Task.Yield();

            // ... snip...
            Window window = GetParentWindow(dependencyObject);

            window.Topmost = true;                                              
        }, 
        // Use an appropriately low priority to defer until 
        // visual tree updated.
        DispatcherPriority.ApplicationIdle);
 }

更新 2

DevExpress を使用している場合、LayoutTreeHelperクラスは、ビジュアル ツリーを上下にスキャンするのに役立ちます。

ビジュアル ツリーを上下にスキャンするサンプル コードについては、次を参照してください。

アップデート 3

添付プロパティを使用している場合、ビジュアル ツリーを確実に読み込む唯一の方法は、イベント ハンドラー内またはLoadedイベント ハンドラーの後でコードを実行することです。この制限を認識していないと、すべてが断続的に失敗します。上記のように、イベントが発生するまで待機するOnLoadedことは、他のランダムな形式の遅延を導入しようとする他の方法よりもはるかに優れています。

DevExpress を使用している場合、これはさらに重要です。Loadedイベントの前に何かをしようとすると、状況によってはクラッシュする可能性があります。

例えば:

  • window.Show()イベントの前に呼び出すLoadedと、状況によってはクラッシュが発生しました。
  • IsVisibleChangedイベントが発生する前にイベント ハンドラーにフックすると、Loaded状況によってはクラッシュが発生します。

免責事項: 私は DevExpress とは関係がありません。DevExpress は多くの優れた WPF ライブラリの 1 つです。Infragistics もお勧めします。

4

2 に答える 2

0

ReSharper (suggest method stubs) でより適切に機能し、優先順位に従ってパラメーターを受け取るため、私はこのバージョンを好みます。

public static class FrameworkElementExtensions
{
    public static void BeginInvoke(this DispatcherObject element, Action action, DispatcherPriority priority = DispatcherPriority.ApplicationIdle)
    {
        element.Dispatcher.BeginInvoke(priority, new Action(async () =>
        {
            await Task.Yield();
            action();
        }));
    }
}
于 2016-04-19T14:02:13.317 に答える