Estilos y Plantillas – ScrollViewer


Hola, ya tenía tiempo de no escribir así que voy a tratar de reivindicarme explicando un poco de cómo hacer estilos y plantillas para nuestros controles. Estaba haciendo un programa cuando me cansé del ScrollViewer que viene por defecto, buscando en Internet encontré algo que me gustó bastante, así que busqué cómo llegar a eso y usando este artículo de Sacha Barber y este de la librería Microsoft terminé con esto:

Para llegar a esto, vamos a tener que cortar mucha tela, así que comencemos con una imagen de lo que vamos a hacer:

Tomada de: http://sachabarber.net/?p=122

Primero que todo crearemos los RepeatButton de las esquinas:

 

 

 

 

    <!-- SrollViewer ScrollBar Repeat Buttons (at each end) -->
    <Style x:Key="ScrollBarLineButton" TargetType="{x:Type RepeatButton}">
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="Focusable" Value="false"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RepeatButton}">
                    <Border
          					Name="Border"
          					Margin="1"
          					CornerRadius="2"
          					Background="{StaticResource NormalBrush}"
          					BorderBrush="{StaticResource NormalBorderBrush}"
          					BorderThickness="1">
                        <Path 	Name="Path"
            					HorizontalAlignment="Center"
            					VerticalAlignment="Center"
            					Fill="{StaticResource GlyphBrush}"
            					Data="{Binding Path=Content,
                						RelativeSource={RelativeSource TemplatedParent}}" />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsPressed" Value="true">
                            <Setter TargetName="Border" Property="Background"
                                		Value="{StaticResource ThumbBrush}" />
                            <Setter TargetName="Path" Property="Fill"
                                		Value="{StaticResource NormalBrush}" />
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground"
                                Value="{StaticResource DisabledForegroundBrush}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

EL siguiente paso es crear los RepeatButton de la mitad, aquellos que son transparentes y que al hacer click podemos bajar/subir ir a la izquierda/derecha de manera más rápida.

    <!-- SrollViewer ScrollBar Repeat Buttons (The part in the middle,
             not the thumb the long area between the buttons ) -->
    <Style x:Key="ScrollBarPageButton" TargetType="{x:Type RepeatButton}">
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="IsTabStop" Value="false"/>
        <Setter Property="Focusable" Value="false"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RepeatButton}">
                    <Border Background="Transparent" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Ahora crearemos el Thumb, aquel que podemos arrastrar y soltar para movernos arriba/abajo o izquierda/derecha.

    <!-- ScrollViewer ScrollBar Thumb, that part that can be dragged
            up/down or left/right Buttons -->
    <Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="IsTabStop" Value="false"/>
        <Setter Property="Focusable" Value="false"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <Border
          					Background="{StaticResource ThumbBrush}"
          					BorderBrush="{TemplateBinding BorderBrush}"
          					BorderThickness="1" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Y ya estamos listos para crear nuestras Scrollbars, la barra vertical quedaría de esta forma:

    <!-- VerticalScrollBar Template using the previously created Templates -->
    <ControlTemplate x:Key="VerticalScrollBar"
            		 TargetType="{x:Type ScrollBar}">
        <Grid >
            <Grid.RowDefinitions>
                <RowDefinition MaxHeight="{StaticResource WidthHeightRepeatButton}"/>
                <RowDefinition Height="0.00001*"/>
                <RowDefinition MaxHeight="{StaticResource WidthHeightRepeatButton}"/>

            </Grid.RowDefinitions>

            <Border
      				Grid.RowSpan="3"
      				CornerRadius="2"
      				Background="{StaticResource ScrollBarBrush}" />
            <RepeatButton
      					Grid.Row="0"
      					Style="{StaticResource ScrollBarLineButton}"
      					Height="18"
      					Command="ScrollBar.LineUpCommand"
      					Content="M 0 4 L 8 4 L 4 0 Z" />
            <Border BorderBrush="Gray" Margin="1,0,0,0" BorderThickness="0.8,0.8,0.8,0.8" CornerRadius="3,3,3,3" Background="Transparent" Grid.Row="1">
                <Track
      					Name="PART_Track"
      					Grid.Row="1"
      					IsDirectionReversed="true">
                    <Track.DecreaseRepeatButton>
                        <RepeatButton
          						Style="{StaticResource ScrollBarPageButton}"
          							Command="ScrollBar.PageUpCommand" />
                    </Track.DecreaseRepeatButton>
                    <Track.Thumb>
                        <Thumb
          						Style="{StaticResource ScrollBarThumb}"
          						Margin="1,0,1,0"
          						Background="{StaticResource ThumbBrush}"
          						BorderBrush="{StaticResource HorizontalNormalBorderBrush}" />
                    </Track.Thumb>
                    <Track.IncreaseRepeatButton>
                        <RepeatButton
          						Style="{StaticResource ScrollBarPageButton}"
          						Command="ScrollBar.PageDownCommand" />
                    </Track.IncreaseRepeatButton>
                </Track>
            </Border>
            <RepeatButton
      					Grid.Row="3"
      					Style="{StaticResource ScrollBarLineButton}"
      					Height="18"
      					Command="ScrollBar.LineDownCommand"
      					Content="M 0 0 L 4 4 L 8 0 Z"/>
        </Grid>
    </ControlTemplate>

Como pueden notar creamos un Grid con 3 filas, la fila del primer RepeatButton, la segunda fila del Track y la última nuevamente un RepeatButton. El código para la barra horizontal es bastante parecido por tal razón no lo pondré.

Pero esto no ha sido todo, tenemos que construir nuestro ScrollViewer usando los ControlTemplate VerticalScrollBar y HorizontalScrollBar. Miremos el código y explico que he hecho:

    <!--ScrollViewer Template-->
    <ControlTemplate x:Key="ScrollViewerControlTemplate" TargetType="{x:Type ScrollViewer}">
    	<Grid x:Name="Grid" Background="{TemplateBinding Background}" >
    		<Grid.ColumnDefinitions>
    			<ColumnDefinition Width="*"/>
    			<ColumnDefinition Name="Column" Width="{StaticResource WidthHeightScrollBarsBorder}"/>
    		</Grid.ColumnDefinitions>
    		<Grid.RowDefinitions>
    			<RowDefinition Height="*"/>
    			<RowDefinition Name="Row" Height="{StaticResource WidthHeightScrollBarsBorder}"/>
    		</Grid.RowDefinitions>
    		<Rectangle x:Name="Corner" Grid.Column="1" Fill="Transparent" Grid.Row="1"/>
    		<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
    		<ScrollBar x:Name="PART_VerticalScrollBar" SnapsToDevicePixels="True" OverridesDefaultStyle="True" Width="{StaticResource WidthHeightScrollbars}" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" Template="{DynamicResource VerticalScrollBar}"/>
    		<ScrollBar x:Name="PART_HorizontalScrollBar" SnapsToDevicePixels="True" OverridesDefaultStyle="True" Height="{StaticResource WidthHeightScrollbars}" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" Template="{DynamicResource HorizontalScrollBar}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
    	</Grid>
    	<ControlTemplate.Triggers>
    		<Trigger Property="VerticalScrollBarVisibility" Value="Disabled">
    			<Setter TargetName="Column" Property="Width" Value="0" />
			</Trigger>
			<Trigger Property="HorizontalScrollBarVisibility" Value="Disabled">
    			<Setter TargetName="Row" Property="Height" Value="0" />
			</Trigger>
			<Trigger Property="VerticalScrollBarVisibility" Value="Hidden">
    			<Setter TargetName="Column" Property="Width" Value="0" />
			</Trigger>
			<Trigger Property="HorizontalScrollBarVisibility" Value="Hidden">
    			<Setter TargetName="Row" Property="Height" Value="0" />
			</Trigger>
    		<Trigger Property="IsEnabled" Value="False">
    			<Setter Property="IsEnabled" TargetName="PART_ScrollContentPresenter" Value="False"/>
    		</Trigger>
    		<Trigger Property="IsMouseOver" Value="False">
    			<Setter Property="Visibility" TargetName="PART_VerticalScrollBar" Value="Collapsed"/>
    			<Setter Property="Visibility" TargetName="PART_HorizontalScrollBar" Value="Collapsed"/>
    		</Trigger>
    	</ControlTemplate.Triggers>
    </ControlTemplate>

A simple vista se ve un poco enredado pero veamos las líneas más importantes:


<ControlTemplate x:Key="ScrollViewerControlTemplate" TargetType="{x:Type ScrollViewer}">

Aquí lo que hacemos es configurar nuestra plantilla para que sólo cambie un ScrollViewer y podamos configurar las propiedades.

Creamos un Grid con dos filas y 2 columnas, la segunda fila y segunda columna contendrán los ScrollViewers ya antes creados.

Los Triggers que ahí aparecen sirven para que cuando la barra horizontal/vertical sea ocultada (hidden) o deshabilitada (disabled), la  fila/columna del Grid que contiene la barra sea puesta en cero (0). Además se le añadió un Trigger para que sólo se muestre la barra mientras el mouse está sobre el ScrollViewer.

Les dejo el proyecto completo ScrollviewerStyle.zip y una imagen en fondo negro y con la barra horizontal oculta. Por cierto, si quieren que al usar la rueda del mouse el ScrollViewer se mueva deben poner el código que tengo en code-behind a su proyecto.

Anuncios

2 Respuestas a “Estilos y Plantillas – ScrollViewer

  1. Prefiero el inglés! Hahahaha

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s