I have a WPF application that runs on a touch screen computer. I'd like to change all of the scroll bars in the app to be much wider. Is there a way to do that globally?
Yo have to override the default template of scrollViewer to increase the width of vertical scrollbar. To apply the template across all your scrollbars put the override style in your App resources -
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter Grid.Column="1"/>
<ScrollBar Name="PART_VerticalScrollBar"
Value="{TemplateBinding VerticalOffset}"
Width="40"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<ScrollBar Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Grid.Column="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can set width of 'PART_VerticalScrollBar' to your desired width (say 40 as in example above).Placing this style under Application Resources (App.xaml) makes it applied across complete application.
You need to create an Style inside of the Resources indicating the TargetType.
This style will be applied to all ScrollBars in your xaml file.
<Window.Resources>
<Style TargetType="{x:Type ScrollBar}">
....
</Style>
I know this is old but I applied Kent's answer from this post-https://stackoverflow.com/questions/1321247/how-to-increase-scrollbar-width-in-wpf-scrollviewer but put it in a resource dictionary.
<ResourceDictionary xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">10</sys:Double>
<sys:Double x:Key="{x:Static SystemParameters.HorizontalScrollBarHeightKey}">10</sys:Double>
//a bunch of styles
</ResourceDictionary>
Related
I tried this without luck.
<ListBox ItemsSource="{Binding Path=Items}" ScrollViewer.CanContentScroll="False">
<ListBox.Resources>
<Style TargetType="ScrollBar">
<Setter Property="Width" Value="4"/>
<Setter Property="Template" Value="{DynamicResource MyScrollBar}"/>
</Style>
</ListBox.Resources>
</ListBox>
Scroll bar template:
<ControlTemplate x:Key="MyScrollBar" TargetType="{x:Type ScrollBar}">
<Track x:Name="PART_Track" Width="4" IsDirectionReversed="True" IsEnabled="{TemplateBinding IsMouseOver}">
<Track.Thumb>
<Thumb>
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Grid>
<Border x:Name="thumb" BorderThickness="0" Background="Gray" Height="{TemplateBinding Height}" Width="4"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Track.Thumb>
</Track>
</ControlTemplate>
The thumb has changed its width. But ListBox still leaves much more space for ScrollBar than I want. How can I decrease the space for ScrollBar?
The ListBox uses a ScrollViewer internally in its control template. The default ScrollViewer template will use the scroll bar width defined in the SystemParameters. A simple way to adapt it is to override the key in the ListBox resources. Please note that there are different keys for the horizontal an vertical scroll bars. You might want to adapt both in the long run.
<ListBox ItemsSource="{Binding Path=Items}" ScrollViewer.CanContentScroll="False">
<ListBox.Resources>
<system:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">4</system:Double>
<Style TargetType="ScrollBar">
<Setter Property="Width" Value="4"/>
<Setter Property="Template" Value="{DynamicResource MyScrollBar}"/>
</Style>
</ListBox.Resources>
</ListBox>
Another way is to create a custom control template for the ScrollViewer. You can refer to the official styles and template documentation for ScrollViewer to get an idea how to build this template. There is already an example, where you can adapt the scroll bar width.
<Style x:Key="MyScrollViewer"
TargetType="{x:Type ScrollViewer}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Grid.Column="1"
BorderThickness="0,1,1,1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<ScrollContentPresenter CanContentScroll="{TemplateBinding CanContentScroll}" />
</Border>
<ScrollBar x:Name="PART_VerticalScrollBar"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Width="4"/>
<ScrollBar x:Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Grid.Column="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can either make this style implicit by omitting the x:Key, so it will be applied to all ScrollViewers in scope or you can create a custom ListBox control template, where you sepcify this template for the internal ScrollViewer in order to apply it only there.
I try to style a ScrollViewer so that the width of the ScrollBar element is changed on a MouseOver. I can style the ScrollViewer and give it an initial width, and it is also possible to change properties on a MouseOver, like the Opacity or Visibility. But I can't change the Width, that property is not changed.
I use this code as an example:
<Style x:Key="myScrollBarStyle" TargetType="{x:Type ScrollBar}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.9" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Opacity" Value="0.4" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="myStyle" TargetType="{x:Type ScrollViewer}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter Grid.ColumnSpan="2" Grid.RowSpan="2"/>
<ScrollBar
Style="{StaticResource myScrollBarStyle}"
Name="PART_VerticalScrollBar"
Grid.Column="1"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar
Style="{StaticResource myScrollBarStyle}"
Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Opacity is changed on a MouseOver but if I add a Width, it is ignored. If I look at ControlTemplate.Triggers then I can change the width on MouseOver but that is the width of the complete ScrollViewer, not the ScrollBar element. Even if I point to the element with the targetname PART_VerticalScrollBar.
Searching the internet only results in solutions to change the visibility or opacity, not the width. I could not find any solution.
Is there a solution to do this in a style?
I have the default ListView ScrollBar and i want to change it to this view:
So i took the ScrollViewer ControlTemplate Example from MSDN
<Style x:Key="LeftScrollViewer" TargetType="{x:Type ScrollViewer}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter Grid.Column="1"/>
<ScrollBar Name="PART_VerticalScrollBar"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<ScrollBar Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Grid.Column="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And out it inside <Window.Resources>.
Now since i am new with WPF i want to ask you what should be my next step to achieve this look.
i found this tutorial and under section Large ScrollBars you can see the view that i want but i don't know where to put this code and how finally to connect the new look with my ListView so any help will appreciate
The Virtualization on my TreeView works when I have only styled the TreeViewItem with this bit of xaml in the style:
<Style.Triggers>
<Trigger Property="VirtualizingStackPanel.IsVirtualizing" Value="true">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
But then if I try and give the TreeView itself a style with Style={Resource} the virtualization breaks, i.e:
<Style x:Key="FontTreeViewStyle" TargetType="{x:Type 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" CornerRadius="1" BorderThickness="1" BorderBrush="{DynamicResource BorderMediumColor}" Background="{DynamicResource ControlLightColor}">
<ScrollViewer Focusable="False" CanContentScroll="False" Padding="4"><!-- Style="{StaticResource MyScrollViewer}"-->
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks in advance!
By specifying CanContentScroll="False" on the ScrollViewer you will always stop it virtualizing
Take a look at why setting ScrollViewer.CanContentScroll to false disable virtualization
If you still have problems double check the visual tree that's created in something like Snoop or WPF Inspector. For virtualization to work the IScrollInfo object (ie the panel) must be the direct child of the ScrollViewer.
http://msdn.microsoft.com/en-us/library/ms750665.aspx
Hope that helps,
Mark
MarkDaniel alredy answered (thanks!) but here is a full example style:
<Style x:Key="ScrollViewerStyle" TargetType="{x:Type ScrollViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter CanContentScroll="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.IsContainerVirtualizable="True" VirtualizingPanel.VirtualizationMode="Recycling"/>
<ScrollBar Name="PART_VerticalScrollBar"
Grid.Column="1"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Style="{DynamicResource ScrollBarStyle}"/>
<ScrollBar Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Style="{DynamicResource ScrollBarStyle}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I'm making a wp7 Silverlight app. I have a ScrollViewer that contains a ListBox of ten elements. However, it only lets me scroll down a tiny bit. What could I be doing wrong?
<ScrollViewer>
<ListBox x:Name="StoryListBox"/>
</ScrollViewer>
The ListBox is filled with items of the following type:
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image x:Name="Thumbnail" Grid.Column="0" Width="89" HorizontalAlignment="Left" VerticalAlignment="Top" />
<TextBlock x:Name="Headline" Grid.Column="1" Grid.Row="0" Style="{StaticResource PhoneTextAccentStyle}" TextWrapping="Wrap" HorizontalAlignment="Left" Width="299" FontSize="23.333" VerticalAlignment="Top" />
<TextBlock x:Name="Teaser" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" HorizontalAlignment="Left" Style="{StaticResource PhoneTextSubtleStyle}" TextWrapping="Wrap" VerticalAlignment="Top" Width="384"/>
</Grid>
What could I be doing wrong here?
I do not see the reason why you would need the ListBox to be embedded within the ScrollViewer. If your ListBox has more items than it display in the viewable area, the ListBox items should scroll by themselves. If you edit the ListBox's style using Expression Blend, the style will look like this -
<Style x:Key="ListBoxListStyle" TargetType="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer
x:Name="ScrollViewer"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
Padding="{TemplateBinding Padding}" >
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can see the ScrollViewer embedded in the ControlTemplate of the ListBox, it takes care of the scrolling of ListBoxItems.
It(Scrolling) is working perfectly after I set the Height of the list box.
The ScrollViewer could ONLY work when it is smaller than which it contains (either width or height). If you do not indict the width or height of the ScrollViewer, it will be stretched to fit its content, and as a result the effect would not be perfect.
So what you need to do is to set a fixed size for your ScrollViewer.
By the way, as indyfromoz said, a ListBox already has a ScrollViewer, so you could remove your outer ScrollViewer, and just set the ListBox's size.