1


0

WPF-TabItemでの奇妙なスクロールバーの動作

次のようなコードがあります。

                    x
                    x
                    x
                    x
                    x
                    x
                    x

奇妙なのは、スクロールバーの動作です-最初のタブを下にスクロールして2番目のタブに切り替えると、スクロールバーも下になります-タブ項目のデータテンプレートが同じ場合、スクロールバーの位置は同期されます。 この問題の解決策について知っていますか?

さらに、コードを変更して2つのデータテンプレート(タブごとに1つ)を作成すると、スクロールバーはその位置をまったく保持しません-つまり、tab1を下にスクロールしてtab2に切り替え、tab1に切り替えた場合、スクロールバーはデフォルトの位置。 これの解決策はありますか?

2 Answer


3


DataTemplate`が使用ごとに個別のインスタンスを作成できるようにするには、 x:Shared`属性を `False`に設定するだけです:


これにより、タブが変更されたときにUIが保持されるという2番目の問題が発生します。 TabControlでのWPF UIの永続性によると、解決策は、「TabControl」のように見える別の「ItemsControl」を使用することです。


1


新しいコントロール ZoomPanel:ScrollViewer`を使用して2番目の問題を解決しました。ここでは、scollbarsの位置が DataContext.GetHashCode() `に従って保存されます。 最適なソリューションではないかもしれませんが、私にとってはうまくいきます。 すべてのタブには独自のViewModelがあるため、スクロールバーの位置は保持されます。

public static readonly Dictionary ScrollbarPositions = new Dictionary();

private void ZoomPanelScrollChanged(object sender, ScrollChangedEventArgs e)
{
    ZoomPanel panel = (ZoomPanel)sender;

    // do not save position when uloading or empty data context
    if(!panel.IsLoaded || this.DataContext == null)
    {
        return;
    }

    // save scrollbar position
    int dataContextHashCode = this.DataContext.GetHashCode();
    Point position = new Point(panel.HorizontalOffset, panel.VerticalOffset);

    if(ScrollbarPositions.ContainsKey(dataContextHashCode))
    {
        ScrollbarPositions[dataContextHashCode] = position;
    }
    else
    {
        ScrollbarPositions.Add(dataContextHashCode, position);
    }
}

private void ZoomPanelLoaded(object sender, RoutedEventArgs e)
{
    if(this.DataContext == null)
    {
        return;
    }

    // load scrollbar position
    int dataContextHashCode = this.DataContext.GetHashCode();
    if (ScrollbarPositions.ContainsKey(dataContextHashCode))
    {
        Point position = ScrollbarPositions[dataContextHashCode];
        this.ScrollToHorizontalOffset(position.X);
        this.ScrollToVerticalOffset(position.Y);
    }
}