2008-10-28 22 views
5

Estoy usando un control TreeView y se desplaza automáticamente a alineación izquierda TreeViewItem cuando se hace clic en uno de ellos. He ido a mirar mis Estilos y Plantillas de Control, pero no he encontrado nada. ¿Existe un controlTemplate predeterminado que cause esto? Quiero deshabilitarloWPF ControlTemplate para desplazarse TreeView Control

Respuesta

7

Los elementos se desplazan porque ScrollViewer llama a BringIntoView() sobre ellos. Entonces, una manera de evitar el desplazamiento es suprimir el manejo del evento RequestBringIntoView. Usted puede tratar de que fuera rápidamente subclasificando TreeView y crear instancias de este control en su lugar:

public class NoScrollTreeView : TreeView 
{ 
    public class NoScrollTreeViewItem : TreeViewItem 
    { 
     public NoScrollTreeViewItem() : base() 
     { 
      this.RequestBringIntoView += delegate (object sender, RequestBringIntoViewEventArgs e) { 
       e.Handled = true; 
      }; 
     } 

     protected override DependencyObject GetContainerForItemOverride() 
     { 
      return new NoScrollTreeViewItem(); 
     } 
    } 
    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new NoScrollTreeViewItem(); 
    } 
} 
0

Parece que he encontrado una buena pista sobre MSDN:

suena así una interacción con el ScrollViewer y el sistema de enfoque .

Cuando un elemento se centró dentro de un ScrollViewer (que es parte de la plantilla TreeView), ScrollViewer es instruido para hacer que el elemento de visible. Responde automáticamente por desplazándose al elemento solicitado.

Los métodos dentro de ScrollViewer que manejan estas solicitudes de enfoque son todas privadas y/o interna para que realmente no puede llegar a ellos. Yo no creo que hay demasiado que puede hacer en este caso; es solo cómo funciona el enfoque.

¿Así es? Seguramente hay una manera de modificar la plantilla TreeView para que el ScrollViewer no tendrá este comportamiento ...

0

Ok, que finalmente fue capaz de obtener el estilo por defecto de esta manera:

 using (Stream sw = File.Open(@"C:\TreeViewDefaults.xaml", FileMode.Truncate, FileAccess.Write)) 
     { 
      Style ts = Application.Current.FindResource(typeof(TreeView)) as Style; 
      if (ts != null) 
       XamlWriter.Save(ts, sw); 
     } 

que produjo:

<Style TargetType="TreeView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:s="clr-namespace:System;assembly=mscorlib" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <Style.Triggers> 
     <Trigger Property="VirtualizingStackPanel.IsVirtualizing"> 
      <Setter Property="ItemsControl.ItemsPanel"> 
       <Setter.Value> 
        <ItemsPanelTemplate><VirtualizingStackPanel IsItemsHost="True" /></ItemsPanelTemplate> 
       </Setter.Value> 
      </Setter> 
      <Trigger.Value> 
       <s:Boolean>True</s:Boolean> 
      </Trigger.Value> 
     </Trigger> 
    </Style.Triggers> 
    <Style.Resources> 
     <ResourceDictionary /> 
    </Style.Resources> 
    <Setter Property="Panel.Background"> 
     <Setter.Value><DynamicResource ResourceKey="{x:Static SystemColors.WindowBrushKey}" /></Setter.Value> 
    </Setter> 
    <Setter Property="Border.BorderBrush"> 
     <Setter.Value><SolidColorBrush>#FF828790</SolidColorBrush></Setter.Value> 
    </Setter> 
    <Setter Property="Border.BorderThickness"> 
     <Setter.Value><Thickness>1,1,1,1</Thickness></Setter.Value> 
    </Setter> 
    <Setter Property="Control.Padding"> 
     <Setter.Value><Thickness>1,1,1,1</Thickness></Setter.Value> 
    </Setter> 
    <Setter Property="TextElement.Foreground"> 
     <Setter.Value><DynamicResource ResourceKey="{x:Static SystemColors.ControlTextBrushKey}" /></Setter.Value> 
    </Setter> 
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility"> 
     <Setter.Value><x:Static Member="ScrollBarVisibility.Auto" /></Setter.Value> 
    </Setter> 
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility"> 
     <Setter.Value><x:Static Member="ScrollBarVisibility.Auto" /></Setter.Value> 
    </Setter> 
    <Setter Property="Control.VerticalContentAlignment"> 
     <Setter.Value><x:Static Member="VerticalAlignment.Center" /></Setter.Value> 
    </Setter> 
    <Setter Property="Control.Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="TreeView"> 
       <Border BorderThickness="{TemplateBinding Border.BorderThickness}" 
         BorderBrush="{TemplateBinding Border.BorderBrush}" 
         Name="Bd" SnapsToDevicePixels="True"> 
        <ScrollViewer CanContentScroll="False" 
            HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" 
            VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" 
            Background="{TemplateBinding Panel.Background}" 
            Padding="{TemplateBinding Control.Padding}" 
            Name="_tv_scrollviewer_" 
            SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" 
            Focusable="False"> 
         <ItemsPresenter /> 
        </ScrollViewer> 
       </Border> 
       <ControlTemplate.Triggers> 
        <Trigger Property="UIElement.IsEnabled"> 
         <Setter Property="Panel.Background" TargetName="Bd"> 
          <Setter.Value> 
           <DynamicResource ResourceKey="{x:Static SystemColors.ControlBrushKey}" /> 
          </Setter.Value> 
         </Setter> 
         <Trigger.Value> 
          <s:Boolean>False</s:Boolean> 
         </Trigger.Value> 
        </Trigger> 
        <Trigger Property="VirtualizingStackPanel.IsVirtualizing"> 
         <Setter Property="ScrollViewer.CanContentScroll" TargetName="_tv_scrollviewer_"> 
          <Setter.Value><s:Boolean>True</s:Boolean></Setter.Value> 
         </Setter> 
         <Trigger.Value> 
          <s:Boolean>True</s:Boolean> 
         </Trigger.Value> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Lo cual, desafortunadamente, no parece útil. No veo ninguna propiedad para detener el enfoque de auto-scroll-focus.

Todavía estás ...

0

Otro dato divertido: hay un valor booleano reemplazable llamada HandlesScrolling que siempre devuelve verdadero. Después de descompilar la fuente, parece que esta propiedad NUNCA se usa (o se está utilizando en algún lugar secreto, oscuro y profundo en XAML). Intenté hacer mi propio control TreeView para establecer este valor en falso y no funcionó.

+0

Agradable. Supongo que podríamos ir a buscar fuentes de .NET, pero ... ya sabes. –

6

después de pasar algunas horas en este problema que encontré una solución que funciona para mí.

solución de brians para evitar el evento RequestBringIntoView en un TreeViewItem de burbujeo fue el primer paso.lamentablemente esto también se detiene un TreeViewItem que se mostrará si cambia el elemento seleccionado mediante programación

yourtreeview.SelectedItem = yourtreeviewitem 

así, para mí la solución es modificar la ControlTemplate de la vista de árbol de la siguiente manera:

<Style x:Key="{x:Type TreeView}" TargetType="TreeView"> 
     <Setter Property="OverridesDefaultStyle" Value="True" /> 
     <Setter Property="SnapsToDevicePixels" Value="True" /> 
     <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/> 
     <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="TreeView"> 
        <Border Name="Border" BorderThickness="0" Padding="0" Margin="1"> 
         <ScrollViewer Focusable="False" CanContentScroll="False" Padding="0"> 
          <Components:AutoScrollPreventer Margin="0"> 
           <ItemsPresenter/> 
          </Components:AutoScrollPreventer> 
         </ScrollViewer> 
        </Border> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

la " autoscrollpreventer" es:

using System; 
using System.Windows; 
using System.Windows.Controls; 

namespace LiveContext.Designer.GUI.Components { 
    public class AutoScrollPreventer : StackPanel 
    { 
    public AutoScrollPreventer() { 

     this.RequestBringIntoView += delegate(object sender, RequestBringIntoViewEventArgs e) 
     { 
      // stop this event from bubbling so that a scrollviewer doesn't try to BringIntoView.. 
      e.Handled = true; 
     }; 

    } 
} 

}

esperanza i t ayuda ..

+0

muy buena solución. – stijn