2010-10-27 104 views
0
奇怪的滾動條行爲

我有以下代碼:WPF - 在TabItem的

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="145" Width="156"> 
    <Window.Resources> 
     <DataTemplate x:Key="tabTemplate"> 
      <ScrollViewer> 
       <StackPanel Orientation="Vertical"> 
        <TextBlock>x</TextBlock> 
        <TextBlock>x</TextBlock> 
        <TextBlock>x</TextBlock> 
        <TextBlock>x</TextBlock> 
        <TextBlock>x</TextBlock> 
        <TextBlock>x</TextBlock> 
        <TextBlock>x</TextBlock> 
       </StackPanel> 
      </ScrollViewer> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid> 
     <TabControl> 
      <TabItem Header="Tab1" ContentTemplate="{StaticResource ResourceKey=tabTemplate}"/> 
      <TabItem Header="Tab2" ContentTemplate="{StaticResource ResourceKey=tabTemplate}"/> 
     </TabControl> 
    </Grid> 
</Window> 

什麼是奇怪的是滾動條的行爲 - 如果我在第一個選項卡上向下滾動,並切換到第二個選項卡,滾動條是失望過 - 當選項卡項目具有相同的數據模板時,滾動條的位置同步。你知道這個問題的任何解決方案嗎?此外,當我修改代碼並創建兩個數據模板(每個標籤一個)時,滾動條根本不保留它們的位置 - 這意味着如果我向下滾動tab1,切換到tab2並再次切換到tab1 ,滾動條處於默認位置。這個的任何解決方案?

回答

2

爲了使DataTemplate爲每個使用創建單獨的實例,只是x:Shared屬性設置爲False

<DataTemplate x:Key="tabTemplate" x:Shared="False"> 

這將導致你的第二個問題,這是保存UI的標籤更改時。根據WPF UI persistence in TabControl,解決方案將使用看起來像TabControl的不同ItemsControl

+0

第一個問題的作品,使用ItemsControl似乎不是我的項目的一個很好的解決方案。但是失去位置並不像滾動條的位置那麼古怪,所以我接受這個解決方案。 – bretik 2010-11-01 08:00:09

1

我使用新控件ZoomPanel : ScrollViewer解決了第二個問題,其中根據DataContext.GetHashCode()保存了scollbars的位置。也許不是最佳的解決方案,但爲我工作。每個選項卡都有自己的ViewModel,所以滾動條的位置被保留。

public static readonly Dictionary<int, Point> ScrollbarPositions = new Dictionary<int, Point>(); 

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); 
    } 
} 
+1

請注意,GetHashCode不保證是唯一的。最安全的方法是在您的ViewModel上添加一個唯一的ID屬性,或者使用控件中的索引保存滾動條位置。 – robertos 2010-11-03 08:31:26

+0

使用索引不是我的選擇,因爲我需要從內部控件中確定選項卡索引。這種方法的下一個問題是可以通過關閉並重新打開選項卡來更改選項卡索引。這不是代碼的重要組成部分,只是增強了GUI,所以我願意冒哈希代碼風險。哈希代碼的好點 - 很好的評論。 – bretik 2010-11-03 09:22:43