10

問題
ViewModel にバインドする Chrome 形状のタブを使用するカスタム タブ コントロールがあります。形状のため、エッジが少し重なっています。TabControl_SelectionChangedタブの選択とタブのドラッグ/ドロップで正常に機能する tabItem の ZIndex を設定する関数がありますが、リレー コマンドを使用してタブを追加または閉じると、異常な結果が得られます。誰にもアイデアはありますか?

デフォルトビュー:

タブの削除:

2 つ以上のタブを続けて追加する:

一度に複数のタブを追加しても、最近追加された他のタブの zindex はリセットされないため、右側のタブの後ろに移動します。また、タブを閉じると、それを置き換える SelectedTab の ZIndex が正しくレンダリングされず、タブの後ろに表示されます。右側のタブ。

ZIndex を設定するコード

private void PrimaryTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.Source is TabControl)
        {
            TabControl tabControl = sender as TabControl;
            ItemContainerGenerator icg = tabControl.ItemContainerGenerator;
            if (icg.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
            {
                foreach (object o in tabControl.Items)
                {
                    UIElement tabItem = icg.ContainerFromItem(o) as UIElement;
                    Panel.SetZIndex(tabItem, (o == tabControl.SelectedItem ? 100 :
                        90 - tabControl.Items.IndexOf(o)));
                }
            }
        }
    }

ブレークポイントを使用すると、ZIndex が目的の値に正しく設定されていることがわかりますが、レイアウトには変更が表示されません。変更のいくつかが有効であることはわかっています。なぜなら、それらのどれも機能していない場合、タブの端が逆になるからです (右のタブが左のタブの上に描画されます)。タブをクリックすると、すべてのタブ (上に描画する必要があるものを含む) の zindex が正しく設定され、それらをドラッグ/ドロップして再配置すると、正しくレンダリングされます (タブ項目が削除され、再挿入されます)。私が考えることができる唯一の違いは、MVVMデザインパターンを使用していることと、タブの追加/閉じるボタンがリレーコマンドであることです。

なぜこれが起こっているのか、どうすれば修正できるのか、誰にもわかりませんか??

ps ViewModel に ZIndex を設定してバインドしようとしましたが、relay コマンドを使用してタブを追加/削除すると同じことが起こります。

4

2 に答える 2

5

ありがとう阿部さん、あなたの2番目のコメントは私の解決策につながります!

tabItem.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);ループの各反復に追加しました。

変更のたびに各 tabItem を更新せずに、他の誰かがこれを回避する方法を見つけた場合、私はまだ学びたいと思っています。ループの最後にタブ コントロール全体を更新しようとしましたが、タブを追加するのではなく、タブを閉じる場合にのみ機能しました。Panel.ZIndex が正しく設定されていることはわかっていますが、レンダリング時にそのプロパティを尊重していません。

編集:上記のコード行は、タブをドラッグ/ドロップすると、ドラッグされているタブの後ろにタブが一時的に表示されるという異常なちらつきを引き起こしていました。コードを別の関数に移動し、ディスパッチャーの優先順位を下げて呼び出したところ、問題が解決しました。最終的なコードは次のとおりです。

private void PrimaryTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.Source is TabControl)
        {
            TabControl tabControl = sender as TabControl;

            tabControl.Dispatcher.BeginInvoke(
                new Action(() => UpdateZIndex(sender as TabControl)),
                DispatcherPriority.Background);
        }
    }

    private void UpdateZIndex(TabControl tabControl)
    {
        ItemContainerGenerator icg = tabControl.ItemContainerGenerator;

        if (icg.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
        {
            foreach (object o in tabControl.Items)
            {
                UIElement tabItem = icg.ContainerFromItem(o) as UIElement;
                if (tabItem != null)
                {
                    // Set ZIndex
                    Panel.SetZIndex(tabItem, (o == tabControl.SelectedItem ? 100 :
                        90 - tabControl.Items.IndexOf(o)));
                }
            }
        }
    }
于 2010-03-30T19:49:10.760 に答える
1

コレクションが変更されたときに、アルゴリズムを再度実行する必要があるようです。プロパティをテストしているためItemContainerGenerator.Status、アルゴリズムが実行されない場合があります。StatusChangedイベントをリッスンし、変更されたときにContainersGeneratedアルゴリズムを再度実行することを検討することをお勧めします。

于 2010-03-26T19:54:31.497 に答える