2010-08-03 77 views
2

嘿所以,有一個關於Silverlight中TreeView控件的問題。Silverlight TreeView ScrollViewer問題

我有一個應用程序動態添加元素到樹視圖。一些元素足夠長,需要水平滾動。當它們被添加到樹形視圖中時,我的樹形視圖一直向左滾動,因此您必須滾動才能看到該項目的結尾。然而,如果我點擊其中一個項目(隱藏樹形視圖),然後使用我實現的「返回結果」按鈕(注意,這隻能處理可見性更改),樹視圖變爲可見,並自動滾動到中央。

有沒有人知道我怎麼可以讓樹形圖一直向左滾動,當我回到結果?

我試着樹視圖模板搞亂:

<Style TargetType="controls:TreeView" x:Name="SCREW"> 
      <Setter Property="Background" Value="#FFFFFFFF" /> 
      <Setter Property="Foreground" Value="#FF000000" /> 
      <Setter Property="HorizontalContentAlignment" Value="Left" /> 
      <Setter Property="VerticalContentAlignment" Value="Top" /> 
      <Setter Property="Cursor" Value="Arrow" /> 
      <Setter Property="BorderThickness" Value="1" /> 
      <Setter Property="Padding" Value="1" /> 
      <Setter Property="BorderBrush" Value="#FF000000" /> 
      <Setter Property="IsTabStop" Value="True" /> 
      <Setter Property="TabNavigation" Value="Once" /> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="controls:TreeView" x:Name="SCREWTEMPLATE"> 
         <Grid> 
          <VisualStateManager.VisualStateGroups> 
           <VisualStateGroup x:Name="CommonStates"> 
            <VisualState x:Name="Normal" /> 
            <VisualState x:Name="MouseOver" /> 
            <VisualState x:Name="Pressed" /> 
            <VisualState x:Name="Disabled" /> 
           </VisualStateGroup> 
           <VisualStateGroup x:Name="FocusStates"> 
            <VisualState x:Name="Unfocused" /> 
            <VisualState x:Name="Focused" /> 
           </VisualStateGroup> 
           <VisualStateGroup x:Name="ValidationStates"> 
            <VisualState x:Name="Valid" /> 
            <VisualState x:Name="InvalidUnfocused"> 
             <Storyboard> 
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Validation" Storyboard.TargetProperty="Visibility"> 
               <DiscreteObjectKeyFrame KeyTime="0" Value="Visible" /> 
              </ObjectAnimationUsingKeyFrames> 
             </Storyboard> 
            </VisualState> 
            <VisualState x:Name="InvalidFocused"> 
             <Storyboard> 
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Validation" Storyboard.TargetProperty="Visibility"> 
               <DiscreteObjectKeyFrame KeyTime="0" Value="Visible" /> 
              </ObjectAnimationUsingKeyFrames> 
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationToolTip" Storyboard.TargetProperty="IsOpen"> 
               <DiscreteObjectKeyFrame KeyTime="0"> 
                <DiscreteObjectKeyFrame.Value> 
                 <System:Boolean>True</System:Boolean> 
                </DiscreteObjectKeyFrame.Value> 
               </DiscreteObjectKeyFrame> 
              </ObjectAnimationUsingKeyFrames> 
             </Storyboard> 
            </VisualState> 
           </VisualStateGroup> 
          </VisualStateManager.VisualStateGroups> 

          <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"> 
           <Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}" Margin="1"> 
            <ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="{x:Null}" BorderBrush="Transparent" BorderThickness="0" IsTabStop="False" TabNavigation="Once" Loaded="ScrollViewer_Loaded"> 
             <ItemsPresenter Margin="5" /> 
            </ScrollViewer> 
           </Border> 
          </Border> 

          <Border x:Name="Validation" Grid.Column="1" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="#FFDB000C" CornerRadius="2" Visibility="Collapsed"> 
           <ToolTipService.ToolTip> 
            <ToolTip x:Name="ValidationToolTip" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" IsHitTestVisible="True" /> 
           </ToolTipService.ToolTip> 
           <Grid Width="10" Height="10" HorizontalAlignment="Right" Margin="0,-4,-4,0" VerticalAlignment="Top" Background="Transparent"> 
            <Path Margin="-1,3,0,0" Fill="#FFDC000C" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 Z" /> 
            <Path Margin="-1,3,0,0" Fill="#FFFFFFFF" Data="M 0,0 L2,0 L 8,6 L8,8" /> 
           </Grid> 
          </Border> 
         </Grid> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

但隨着這個問題是我不知道如何從後面的代碼訪問的ScrollViewer ...所以我不能打電話ScrollView.setScrollOffset(0d,0d)或類似的東西。

任何想法?太感謝了。

最後一件事,我想盡量避免實現一個擴展treeview的新控件。我真的希望有一種方法可以訪問/修改和使用與c#代碼隱藏的控件模板相關的函數。

回答

0

我只是爲此設置了一個附屬屬性並在那裏創建了你想要的邏輯。然後你會用附加的屬性裝飾你的樹形視圖。

var offset = this.HorizontalScrollOffsetAfterSelect; // would be 0 if you don't want to make that adjustable 
if (!Double.IsNaN(offset)) 
{ 
    var scrollViewer = trv.GetVisualDescendants().OfType<ScrollViewer>().FirstOrDefault(); 
    if (scrollViewer != null) 
    { 
     scrollViewer.ScrollToHorizontalOffset(offset); 
     // and because that wasn't enough because of timing issues: 
     var scrollBar = scrollViewer.GetVisualDescendants().OfType<ScrollBar>().Where(cur => cur.Orientation == Orientation.Horizontal).FirstOrDefault(); 
     if (scrollBar != null) 
     { 
      RoutedPropertyChangedEventHandler<double> handler = null; 
      handler = (sender, e) => 
       { 
        scrollBar.ValueChanged -= handler; 

        scrollViewer.ScrollToHorizontalOffset(offset); 
       }; 
      scrollBar.ValueChanged += handler; 
     } 
    } 
} 

要求:處理SelectedItemChanged事件TreeView

public class ScrollResetService 
{ 
    public static DependencyProperty IsScrollResetProperty = DependencyProperty.RegisterAttached("IsScrollReset", 
                           typeof(bool), 
                           typeof(ScrollResetService), 
                           new PropertyMetadata(false, 
                             OnIsScrollResetChanged)); 
    public static void SetIsScrollReset(DependencyObject d, bool value) 
    { 
     d.SetValue(IsScrollResetProperty, value); 
    } 

    public static bool GetIsScrollReset(DependencyObject d) 
    { 
     return d.GetValue(IsScrollResetProperty) == null ? false : (bool)d.GetValue(IsScrollResetProperty); 
    } 

    private static void OnIsScrollResetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var treeView = d as TreeView; 
     bool isScrollReset; 
     if (e.NewValue!= null && bool.TryParse(e.NewValue.ToString(), out isScrollReset) && treeView != null) 
     { 

      treeView.SelectedItemChanged += (sender, args) => 
               { 
                var scrolls = 
                 treeView.GetAllLogicalChildrenOfType<IScrollInfo>(); 
                scrolls.ForEach(i => i.SetVerticalOffset(0)); 
               }; 

     } 
    } 

} 

public static class Extensions 
    { 

public static IEnumerable<T> GetAllLogicalChildrenOfType<T>(this FrameworkElement parent) 
     { 
      Debug.Assert(parent != null, "The parent cannot be null."); 
      return parent.GetVisualChildren().Flatten(item => item.GetVisualChildren()).OfType<T>(); 
     } 

public static IEnumerable<T> Flatten<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> childSelector) 
     { 
      if (items == null) return Enumerable.Empty<T>(); 
      return items.Concat(items.SelectMany(i => childSelector(i).Flatten(childSelector))); 
     } 

internal static IEnumerable<DependencyObject> GetVisualChildren(this DependencyObject parent) 
     { 
      int childCount = VisualTreeHelper.GetChildrenCount(parent); 
      for (int counter = 0; counter < childCount; counter++) 
      { 
       yield return VisualTreeHelper.GetChild(parent, counter); 
      } 
     } 
} 
+0

對不起,聽起來像這樣可以工作,但你將不得不幫助我多一點。 你能告訴我如何使用它們嗎?謝謝,如果這有效果,我欠你一輩子! – NickHalden 2010-08-03 19:49:11

0

我把這個代碼放到一個行爲(也將在後面的代碼工作):我們做的是含有scrollviewers其他控件類似的東西using System.Linq;using System.Windows.Controls.Primitives;和工具包ofc。

到目前爲止對我來說工作得不錯。