I need to make the vertical scrollbar a bit lower (shorter) because I need a space for a little button The button will be hovered over the ScrollViewer in the upper right corner. I would like to avoid separating the scrollbar out of the ScrollViewer just to add my button there.
It's a standard WPF ScrollViewer with
<ScrollViewer Name="Scroller" CanContentScroll="True" VerticalScrollBarVisibility="Auto" Height="{Binding ElementName=OuterContainer, Path=ActualHeight}" Width="{Binding ElementName=OuterContainer, Path=ActualWidth}">
<Grid Name="Container" Margin="5,5,5,5">
</Grid>
</ScrollViewer>
Is there any way I can style (or C# code) some hack which will free some space (it would be top margin, I guess) above the vertical scrollbar?
I would change the ScrollViewers style. According to the MSDN library http://msdn.microsoft.com/en-us/library/aa970847.aspx the default style is
<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>
<Border Grid.Column="1"
BorderThickness="0,1,1,1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<ScrollContentPresenter />
</Border>
<ScrollBar x:Name="PART_VerticalScrollBar"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<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>
So you could replace the vertical scroll bar as
<ScrollBar x:Name="PART_VerticalScrollBar"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
**Margin="0,12,0,0"**/>
Related
I have a custom Scroll bar style, but it has this annoying little white square. I want to remove it, any ideas how?
Annoying Little White Square:
Edit: it might be a repeat button, I think
The problem is clearly related to your style.
And how to answer your question without seeing this style?
Based on my attempt to guess what you might have in the style, but I assume that you do not change the default ScrollViewer template, you only set values for its properties.
If you look at the default template, there is a rectangle x:Name="Corner" in the corner between the ScrollBar's.
<ControlTemplate x:Key="ScrollViewerControlTemplate.Default"
TargetType="{x:Type ScrollViewer}">
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle x:Name="Corner"
Grid.Column="1" Grid.Row="1"
Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
Grid.Column="0" Grid.Row="0"
CanContentScroll="{TemplateBinding CanContentScroll}"
CanHorizontallyScroll="False" CanVerticallyScroll="False"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"/>
<ScrollBar x:Name="PART_VerticalScrollBar"
Grid.Column="1" Grid.Row="0"
AutomationProperties.AutomationId="VerticalScrollBar"
Cursor="Arrow"
Maximum="{TemplateBinding ScrollableHeight}" Minimum="0"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
ViewportSize="{TemplateBinding ViewportHeight}"/>
<ScrollBar x:Name="PART_HorizontalScrollBar"
AutomationProperties.AutomationId="HorizontalScrollBar"
Cursor="Arrow"
Grid.Column="0" Grid.Row="1"
Maximum="{TemplateBinding ScrollableWidth}"
Minimum="0"
Orientation="Horizontal"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
ViewportSize="{TemplateBinding ViewportWidth}"/>
</Grid>
</ControlTemplate>
The background color of this rectangle is set by DynamicResource with key {x:Static SystemColors.ControlBrushKey}.
Therefore, all you can do without changing the template is to create a new resource with the same key, but with a different color.
The resource can be set in the same place where you set your style.
An example of defining this resource:
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Red"/>
If you do change the template, then you can simply delete this rectangle, then this corner will be the background color of the ScrollViewer.
You can also, after removing it, stretch one of the ScrollBars to this corner.
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
I have a ScrollViewer which appears on the right hand side when enough objects are in the list. How can I make it appear on the left hand side?
<ListBox
x:Name="MessageListBox"
BorderThickness="0"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
HorizontalContentAlignment="Stretch"
AlternationCount="2"
ItemContainerStyle="{StaticResource AltStyle}"
SelectionMode="Extended">
<ListBox.ItemTemplate>
<DataTemplate>
<!-- button -->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
It can be achieved by wrapping the list into ScrollViewer and changing the ScrollViewer property FlowDirection to RightToLeft. Also don't forget to restore the lists FlowDirection to LeftToRight otherwise it will inherit the parent's direction.
<ScrollViewer FlowDirection="RightToLeft"
CanContentScroll="False" VerticalScrollBarVisibility="Auto">
<ListBox ItemsSource="{Binding CustomItems}" FlowDirection="LeftToRight"/>
</ScrollViewer>
I found it on MSDN social blogs,
How to Set VerticalScroll bar on Left side
This is accomplished by modifying the template of the ListBox's ScrollViewer.
Start by modifying the ColumnDefinitions for the container Grid. Then, put things into the correct columns.
Have fun!
<!--This should be able to be placed on any WPF Window for testing purposes-->
<ListBox Height="85" VerticalAlignment="Top" Margin="117,110,300,0">
<ListBox.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle x:Name="Corner" Grid.Column="0" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="1" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
<ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
<ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ListBox.Template>
<TextBox Text="Hi Mom!"/>
<TextBox Text="Hi Dad!"/>
<TextBox Text="Hi Father!"/>
<TextBox Text="Hi Mother!"/>
<TextBox Text="Hi Padre!"/>
</ListBox>
P.S. If you wanted to move the HorizontalScrollBar, simply reorder the RowDefinitions, the do the same exercise (put every child component in the proper row)
My solution is to set RightToLeft FlowDirection for ListView and then set LeftToRight for ItemsPanelTemplate child StackPanel.
<ListView FlowDirection="RightToLeft" ItemsSource="{Binding SomeDataSource}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel FlowDirection="LeftToRight"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
Original ListView shown on the right and ListView with scrollbar positioned on the left (by source code above) - shown on the left.
Simply set the ListBox's embedded scrollviewer to RightToLeft:
<ListBox ScrollViewer.FlowDirection="RightToLeft" />
Summary: I would like to specify the cursor used over the ScrollViewer's disabled scrollbar.
Paste this into Kaxaml and move the mouse over the disabled vertical scrollbar. Notice that it's using the Cross cursor I specified for the ScrollViewer. Contrast this with the arrow cursor used on the enabled horizontal scrollbar.
I don't want the Cross to show over the disabled vertical scrollbar as it would imply that a particular action is possible when it's not (this is just an example, my app uses different cursors). I would prefer the arrow; can anyone tell me how to accomplish this?
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical">
<ScrollViewer Height="300" Width="300" HorizontalScrollBarVisibility="Visible"
Cursor="Cross">
<Canvas Width="2000">
<Button Canvas.Left="5" Canvas.Top="5">Left</Button>
<Button Canvas.Left="1900" Canvas.Top="5">Right</Button>
</Canvas>
</ScrollViewer>
</StackPanel>
</Page>
You will need to set the Cursor at the ScrollBar level, possibly even a lower level if you want individual buttons on the scroll bar to have different cursors. Unfortunately, the cursor for ScrollBars is hard-coded by the ScrollViewer template, so you will need to re-template it.
Here's a simple example (updated after comments):
<Window x:Class="SO8067799.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="ScrollViewer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" 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"/>
<Grid x:Name="verticalGrid" Grid.Column="1" Cursor="Hand">
<ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
</Grid>
<Grid x:Name="horizontalGrid" Grid.Row="1" Grid.Column="0" Cursor="Hand">
<ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="PART_VerticalScrollBar" Property="IsEnabled" Value="False">
<Setter TargetName="verticalGrid" Property="Cursor" Value="No"/>
</Trigger>
<Trigger SourceName="PART_HorizontalScrollBar" Property="IsEnabled" Value="False">
<Setter TargetName="horizontalGrid" Property="Cursor" Value="No"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel Orientation="Vertical">
<ScrollViewer Height="300" Width="300" HorizontalScrollBarVisibility="Visible">
<Canvas Width="2000">
<Button Canvas.Left="5" Canvas.Top="5">Left</Button>
<Button Canvas.Left="1900" Canvas.Top="5">Right</Button>
</Canvas>
</ScrollViewer>
</StackPanel>
</Window>
I have a WPF ScrollViewer, and I would like to get to the ScrollContentPresenter of it's template.
If you wish to get to the ScrollContentPresenter of a ScrollViewer you can use a ControlTemplate
<ScrollViewer Style="{StaticResource LeftScrollViewer}"/>
<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>
Instead of trying to go down the tree from ScrollViewer, maybe you want to bind something from the Content up?
Something like:
<Grid Width={Binding Path=ActualWidth RelativeBinding={RelativeBinding FindAncestor, AncestorType={x:Type ScrollContentPresenter}}}>
Note: That syntax might not be 100% right, it's off the top of my head