Changing viewport of datagrid - wpf

I need to change viewport of datagrid to maximum so all rows are propagated in constructor. So I used Scrollview with row height set to auto.
<ScrollViewer>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<DataGrid>
</DataGrid>
</Grid>
</ScrollViewer>
This propagates all controls but now when I use scrollbar it also moves header row. I need that the scrollbar will effect only datagrid.

I dont understand this statement
... need to change viewport of datagrid to maximum so all rows are
propagated in constructor. So I used Scrollview with row height set to
auto...
... where is the Viewport setting in the code? Also what is this constructor? Your terminologies are confusing....
However I can assume what you want is the datagrid to fully render its rows (without extra space below rows) and occupy that entriely over the grid panel. But because you have used a scroll viewer abone grid, it will scroll datagrid headers as well.
If you use "Snoop" you will find that wpf datagrid has a scroll viewer as its visual child and it has a Grid panel in its own template, there the ScrollContentPresenter is under a Grid.Row which has RowDefinition that has Height as asterick (*).
Using visual children extraction method given below, accesss that Grid descendent and change its height to auto.
(GetVisualChild<Grid>(myDataGrid)).RowDefintions[1].Height="Auto"
Method to snoop through all children of a parent...
static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null) child = GetVisualChild<T>(v);
if (child != null) break;
}
return child;
}
The XAML way
Override the dataGrid Control template...
<Style TargetType="{x:Type DataGrid}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGrid}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True"
Padding="{TemplateBinding Padding}">
<ScrollViewer Focusable="false"
Name="DG_ScrollViewer">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <!--This changed to Auto from '*'-->
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!--Left Column Header Corner -->
<Button Command="{x:Static dg:DataGrid.SelectAllCommand}"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=CellsPanelHorizontalOffset}"
Template="{StaticResource SelectAllButtonTemplate}"
Focusable="false"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=HeadersVisibility, Converter={x:Static dg:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static dg:DataGridHeadersVisibility.All}}" />
<!--Column Headers-->
<dgp:DataGridColumnHeadersPresenter Grid.Column="1"
Name="PART_ColumnHeadersPresenter"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=HeadersVisibility, Converter={x:Static dg:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static dg:DataGridHeadersVisibility.Column}}"/>
<!--DataGrid content-->
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.Row="1" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" />
<ScrollBar Grid.Row="1" Grid.Column="2" Name="PART_VerticalScrollBar"
Orientation="Vertical"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<Grid Grid.Row="2" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ScrollBar Grid.Column="1"
Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

Get Header name

Hello I am a bit lost with the control Templates, I have an expander and some control-styles that apply onto the Expander.
So the idea is to let the User insert the header
<Expander Name="MyExpanderExpander" Style="{StaticResource MyExpanderNewGeneration}" Header="UserChoice" OverridesDefaultStyle="True" VerticalAlignment="Top" Margin="0,0,0,0" Height="210">
So now the Style : MyExpanderNewGeneration should get the header Name : UserChoic
The ToggleButton has to get the Header Name : UserChoice and here is my problem ..but how to do it?
my Style applying is
<Style TargetType="Expander" x:Key="MyExpanderNewGeneration" BasedOn="{StaticResource BaseControlStyle}" >
<!--x:Key="GroupBoxStyle"-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Expander">
<Grid>
<!--Grid Rows split the GroupBox into two areas -->
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Header area-->
<Border Name="HeaderArea"
Grid.Row="0"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="1"
CornerRadius="2,2,0,0" >
<ToggleButton x:Name="ExpanderButton"
Grid.Row="0"
Grid.Column="0"
Margin="0,0,0,0"
VerticalAlignment="Top"
Template="{StaticResource TestToggleButton}"
Content="{TemplateBinding Header}"
IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True">
</ToggleButton>
Herer I want to get the UserChoice Name.
<ControlTemplate x:Key="TestToggleButton" TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Foreground="White" Width="300" Grid.Column="0" FontSize="15"
HorizontalAlignment="Left" FontWeight="Normal" Something={HEADER???}
How to solve this?
Since you are setting Content="{TemplateBinding Header}" in your ExpanderButton, you will need to bind to the Content property inside your TestToggleButton style's control template:
<ControlTemplate x:Key="TestToggleButton" TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label
...
Content={TemplateBinding Content} />
...
</Grid>
</ControlTemplate>

SmallChange in a XAML ScrollViewer ControlTemplate has no effect

I've created a basic Windows Desktop WPF Application. In the MainWindow, I've added the following as the body of the window:
<ScrollViewer Template="{DynamicResource ScrollViewerControlTemplate1}">
<ScrollViewer.Resources>
<ControlTemplate x:Key="ScrollViewerControlTemplate1" 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"/>
<ScrollBar x:Name="PART_VerticalScrollBar" 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}" SmallChange="40000"/>
<ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" 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.Resources>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="300"/>
<RowDefinition Height="300"/>
<RowDefinition Height="300"/>
<RowDefinition Height="300"/>
<RowDefinition Height="300"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="SteelBlue"/>
<Border Grid.Row="1" Background="Peru"/>
<Border Grid.Row="2" Background="Goldenrod"/>
<Border Grid.Row="3" Background="Tomato"/>
<Border Grid.Row="4" Background="IndianRed"/>
</Grid>
</ScrollViewer>
You'll notice that on PART_VerticalScrollbar, I've set the SmallChange="40000" (an arbitrarily large number). Yet when I click the up/down arrows on the scrollbar, it does the same very small change as it did before I set the SmallChange to anything.
I've read over the documentation a number of times, and can't figure out why this isn't having any effect on the amount that the ScrollViewer scrolls. Any ideas?
Note that I could change the ScrollBar template and change the command these button calls to Scrollbar.PageUpCommand rather than Scrollbar.LineUpCommand, but ultimately I'd like to have finer control over the scrolling than a full page.
The reason for this is a special logic implemented in the ScrollViewer and in the ScrollBar.
The ScrollBar.SmallChange property will be only considered for scrolling if the scroll bar is stand-alone. That means, when it is outside of a ScrollViewer.
If you look at the ScrollViewer.OnApplyTemplate method, you will notice the following:
public override void OnApplyTemplate()
{
// ...
ScrollBar scrollBar = GetTemplateChild(HorizontalScrollBarTemplateName) as ScrollBar;
if (scrollBar != null)
scrollBar.IsStandalone = false;
// Same for the vertical scroll bar
// ...
}
If a ScrollViewer finds scroll bars inside of it, it sets their IsStandalone (internal) properties to false, which disables the scroll command handing of the scroll bars. Instead, the ScrollViewer takes over the scroll command handing, but it ignores some ScrollBar's properties, including the SmallChange property.
TL;DR This won't work for the scroll bars inside of a ScrollViewer. You can change your template so use two "external" scroll bars. But then, you will need to connect those scroll bars with the ScrollViewer manually.
I suspect that your custom control template isn't being used because of the way you are referencing it. I would change the XAML to this:
<ScrollViewer>
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid ...>
...
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
... ScrollViewer content goes here
</ScrollViewer>
Basically, set the control's template directly, rather than using a dynamic resource.

Why does a WPF DataGrid sometimes remain horizontally shrunk?

I have a user who sometimes sees a DataGrid that doesn't expand to fit its space: visually squeezed data grid http://www.varigence.com/images/compressedDataGrid.jpg.
I'm looking to solve the mystery of why this is happening. Usually, when the Grid first loads, the DataGrid will appear shrunk for a moment, but then expands to fill the appropriate space. The sole lead I have is that the user who sees this says it doesn't repro when he disables Aero in Windows.
I've added a (simplified) snippet of the XAML I'm using below.
Does anyone out there have ideas as to the cause?
Thanks,
-Craig
<Grid
AllowDrop="True"
Background="White"
MinHeight="400"
MinWidth="1100"
MaxHeight="{Binding RelativeSource={RelativeSource AncestorType={x:Type Editors:DesignerEditor}}, Path=MainWindowScrollViewer.ViewportHeight, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxWidth="{Binding RelativeSource={RelativeSource AncestorType={x:Type Editors:DesignerEditor}}, Path=MainWindowScrollViewer.ViewportWidth, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="350" Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition MinWidth="250" Width="*"/>
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
BorderThickness="1"
BorderBrush="{StaticResource headerBackgroundBrush}"
CornerRadius="4"
HorizontalAlignment="Stretch"
Margin="10,10,0,10"
VerticalAlignment="Stretch"
>
<Grid
KeyboardNavigation.TabNavigation="Local"
>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Text="Columns"
/>
<DataGrid:SelectingDataGrid
x:Name="columnDataGrid"
Grid.Row="1"
AutoGenerateColumns="False"
BorderBrush="{StaticResource excelBorderBrush}"
HorizontalAlignment="Left"
ItemsSource="{Binding ElementName=tableEditor, Path=SelectedContext.Columns.FilterCollection}"
RowDetailsTemplateSelector="{StaticResource columnDetailsTemplateSelector}"
RowDetailsVisibilityMode="VisibleWhenSelected"
SelectionMode="Extended"
SelectionUnit="FullRow"
>
<DataGrid:SelectingDataGrid.ItemContainerStyle>
<Style
TargetType="{x:Type DataGridRow}"
BasedOn="{StaticResource {x:Type DataGridRow}}"
>
<Setter
Property="IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}"
/>
</Style>
</DataGrid:SelectingDataGrid.ItemContainerStyle>
<DataGrid:SelectingDataGrid.Columns>
...
</DataGrid:SelectingDataGrid.Columns>
</DataGrid:SelectingDataGrid>
</Grid>
</Border>
<GridSplitter
Grid.Column="1"
Background="White"
IsTabStop="False"
ResizeBehavior="PreviousAndNext"
Width="20"
/>
I'm going to assume that you want the DataGrid to fill up the left column. If you change
HorizontalAlignment="Left"
to
HorizontalAlignment="Stretch"
it should solve the problem.

what the name for the item in the green circle

what's the element name in the green circle? Whta's the event corresponding to click this element?
Interestingly, this part of the DataGrid is no-man's-land - it doesn't even have an official name, let alone a behaviour or a template. In order to handle events related to this area, see here or here.
I call it the 'select all' button. However, it doesn't have an official name. It also does not have any style properties exposed. For a simple method to style it via attached properties, see the following:
http://www.scottlogic.co.uk/blog/colin/2009/02/styling-hard-to-reach-elements-in-control-templates-with-attached-behaviours/
Colin E.
As others have stated, it's the "Select All" Button. Clicking it will select everything in the DataGrid if SelectionMode is set to Extended.
The "Select All" Button is part of the DataGrid Template. Or actually, it's part of the ScrollViewer Template that is part of the DataGrid Template so it's nested pretty deep. The ControlTemplate looks like this. From here you can do anything you want with the SelectAll Button, disable it, change the Background etc.
<Style TargetType="{x:Type DataGrid}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate 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>
<!-- Here it is -->
<Button Command="{x:Static DataGrid.SelectAllCommand}" Focusable="false" 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" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" 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 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>
</Setter.Value>
</Setter>
</Style>
If you want to disable the selectall button you can also do like this:
//Disable select all button
datagrid.CommandBindings.Add(new CommandBinding(DataGrid.SelectAllCommand, delegate { }, (s, a) => { if (a.OriginalSource is Button) ((Button)a.OriginalSource).IsEnabled = false; }));
as a workaround.
This can also be used to wire other things up.
The "problem" with re-templating is that you have to take all the themes into account... tedious :)
In at least one example I found, clicking the gray triangle in the corner causes all rows to be selected.
But this is not a built-in feature of this control as far as I know. It is part of a custom template.
See this example:
http://www.dotnetspark.com/kb/2941-styling-wpf-datagrid.aspx
If you download the sample, and search the Resources/DataGridCustomization.xaml file for "SelectAll", you'll find the part of the template that contains this feature.

Disabling text selection in DocumentViewer

Simple question. How do you disable the text selection of DocumentViewer in WPF? This is the feature where an XPS document is displayed by the viewer and then text can be highlighted via mouse. The highlighted text can also be copied but I have already disabled this. I just don't know how to disable the highlighting.
Thanks!
you may use IsFocusable=false. But search box will be disabled too...
We have solved this by overriding the ControlTemplate of the ScrollViewer embedded in the DocumentViewer control. Insert the Style below in "Window.Resources":
<Style TargetType="{x:Type ScrollViewer}" x:Key="CustomScrollPresenter">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid Background="{TemplateBinding Panel.Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle Grid.Column="1" Grid.Row="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
<ScrollContentPresenter
PreviewMouseLeftButtonDown="ScrollContentPresenter_PreviewMouseLeftButtonDown"
Grid.Column="0"
Grid.Row="0"
Margin="{TemplateBinding Control.Padding}"
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
CanContentScroll="{TemplateBinding ScrollViewer.CanContentScroll}" />
<ScrollBar
x:Name="PART_VerticalScrollBar"
Grid.Column="1"
Grid.Row="0"
Minimum="0"
Maximum="{TemplateBinding ScrollViewer.ScrollableHeight}"
ViewportSize="{TemplateBinding ScrollViewer.ViewportHeight}"
Value="{Binding Path=VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Visibility="{TemplateBinding ScrollViewer.ComputedVerticalScrollBarVisibility}"
Cursor="Arrow" AutomationProperties.AutomationId="VerticalScrollBar" />
<ScrollBar
x:Name="PART_HorizontalScrollBar"
Orientation="Horizontal" Grid.Column="0" Grid.Row="1" Minimum="0"
Maximum="{TemplateBinding ScrollViewer.ScrollableWidth}" ViewportSize="{TemplateBinding ScrollViewer.ViewportWidth}" Value="{Binding Path=HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" Visibility="{TemplateBinding ScrollViewer.ComputedHorizontalScrollBarVisibility}" Cursor="Arrow" AutomationProperties.AutomationId="HorizontalScrollBar" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then override the Style of ScrollViewer with it in the ControlTemplate for DocumentViewer:
<Style
x:Key="MyDVStyleExtend"
BasedOn="{StaticResource {x:Type DocumentViewer}}"
TargetType="{x:Type DocumentViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DocumentViewer">
<Border BorderThickness="2,2,2,2"
BorderBrush="SlateBlue" Focusable="False">
<Grid Background="{StaticResource GridBackground}"
KeyboardNavigation.TabNavigation="Local">
<Grid.ColumnDefinitions>
<ColumnDefinition Width ="*"/>
</Grid.ColumnDefinitions>
<ScrollViewer Style="{StaticResource CustomScrollPresenter}" Grid.Column ="0"
CanContentScroll="True"
HorizontalScrollBarVisibility="Auto"
x:Name="PART_ContentHost"
IsTabStop="True"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then create a function for the "PreviewMouseLeftButtonDown="ScrollContentPresenter_PreviewMouseLeftButtonDown"" attribute stated in the CustomScrollPresenter style.
private void ScrollContentPresenter_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
Another way would be to add e.g. a dockpanel:
<DockPanel Name="pnlTouchTaker"
VerticalAlignment="Bottom" HorizontalAlignment="Left"
Background="Transparent">
</DockPanel>
lying "above" the documentviewer and set it´s width and height to the actual width and height of the scrollviewer content in e.g. page loading event.
You might have to add additional logic if using zoom options and the horizontal toolbar becomes visible.
Implement the following code in xaml.cs part (DocumentViewerInstance x:Name of your DocumentViewer in your xaml.)
DocumentViewerInstance.GetType().GetProperty("IsSelectionEnabled", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(DocumentViewerInstance, false, null);
You can use the IsFocusable=false or IsHitTestVisible = false or handle any preview event (for example in accepted answer) for disable selection but the hyperlinks won't work! If you set IsSelectionEnabled = false, the selection will be disabled but hyperlinks will work too. (Warning! IsSelectionEnabled can be changed for true value after you set false, so you should check the value often.)

Resources