White square on area with scrollbar - wpf

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.

Related

WPF DataGrid: Remove internal scrollviewer from datagrid without distorting ControlTemplate

Please i need some on how to remove the internal scrollviewer from the DataGrid's controltemplate in wpf. Below is the ControlTemplate containing the ScrollViewer. Any idea on how to remove the scrollviewer and the scrollbars from the template without destroying the functionality of the datagrid?
I have a custom scrollbar that i have designed to use in my app so the internal scrollviewer in the datagrid wouldn't allow me to do smooth scrolling. Leaving me with two choices. Either i remove the internal scrollviewer from the datagrid control template that i will post below or i remove my custom scrollbars. I want to keep my custom scrollbar so i need help in removing the one in the control template.
i have tried to replace the ScrollviewerControl with a StackPanel and then remove the scrollbars completely but i get an error message saying
The member "Template" is not recognized or is not accessible
Any help will be appreciated
Here is the Control template i want to modify
<ControlTemplate x:Key="DataGridControlTemplate1" TargetType="{x:Type DataGrid}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="DG_ScrollViewer" Focusable="False">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Command="ApplicationCommands.SelectAll" Focusable="False" Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}}">
<Button.Visibility>
<Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
<Binding.ConverterParameter>
<DataGridHeadersVisibility>All</DataGridHeadersVisibility>
</Binding.ConverterParameter>
</Binding>
</Button.Visibility>
</Button>
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.Column="1">
<DataGridColumnHeadersPresenter.Visibility>
<Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
<Binding.ConverterParameter>
<DataGridHeadersVisibility>Column</DataGridHeadersVisibility>
</Binding.ConverterParameter>
</Binding>
</DataGridColumnHeadersPresenter.Visibility>
</DataGridColumnHeadersPresenter>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" Grid.ColumnSpan="2" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Grid.Row="1"/>
<ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="2" Maximum="{TemplateBinding ScrollableHeight}" Orientation="Vertical" Grid.Row="1" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
<Grid Grid.Column="1" Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
</Grid>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
</ControlTemplate>

Controlling ScrollViewer's vertical scrollbar height

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"**/>

How to make the implicit ScrollViewer appear on the left hand side instead of right hand side

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" />

Binding to properties in a custom ControlTemplate

I have a custom data style grid that I have defined in a seperate resource file. In this style I override the ControlTemplate to change it's appearance.
Then I have my own CustomDataGrid control that is derived from UserControl and uses the style in the resource file.
I need to be able to have the vertical scroll bars have a user defined width. I know how to change the scroll bar width by hard coding a value. What I cannot do is make is so that in my custom control I can set the scroll bar width.
Here is what my Template style looks like in the resource file, where I need the scroll bar width I have a series of question marks.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGrid}">
<Border x:Name="border" SnapsToDevicePixels="True" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Background="{TemplateBinding RowBackground}">
<ScrollViewer x:Name="DG_ScrollViewer" Focusable="false" Background="Black">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Focusable="false" Command="{x:Static DataGrid.SelectAllCommand}"
Style="{DynamicResource {ComponentResourceKey
ResourceId=DataGridSelectAllButtonStyle,
TypeInTargetAssembly={x:Type DataGrid}}}"
Visibility="{Binding HeadersVisibility,
ConverterParameter={x:Static DataGridHeadersVisibility.All},
Converter={x:Static DataGrid.HeadersVisibilityConverter},
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
Width="{Binding CellsPanelHorizontalOffset,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.Column="1" Height="32"
Visibility="{Binding HeadersVisibility,
ConverterParameter={x:Static DataGridHeadersVisibility.Column},
Converter={x:Static DataGrid.HeadersVisibilityConverter},
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.ColumnSpan="2"
Grid.Row="1" CanContentScroll="{TemplateBinding CanContentScroll}" />
<ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2"
Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}"
Maximum="{TemplateBinding ScrollableHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Width="{????????????????????????}"
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<Grid Grid.Column="1" Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="1" Orientation="Horizontal"
ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Value="{Binding HorizontalOffset, Mode=OneWay,
RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
Can anyone please help me?
Create a dependency property named (eg) ScrollBarWidth, then write Width={TemplateBinding ScrollBarWidth} in the template.

WPF Reference ScrollContentPresenter of ScrollViewer Template

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

Resources