I'm using .NET 4.5/VS2012, and I have a ListView looks something like this
<ListView
VirtualizingPanel.IsContainerVirtualizable="True"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
Grid.Row="1"
Name="eventLogList"
Margin="5,0,5,0"
BorderBrush="Black"
BorderThickness="2"
ItemsSource="{Binding EventLogs}"
SelectedItem="{Binding SelectedEventLog}"
local:ListViewSorter.CustomListViewSorter="EventLogViewer.UI.EventLogItemComparer"
SelectionMode="Single">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="False">
<GroupStyle.ContainerStyle>
<Style TargetType="GroupItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupItem">
<Expander IsExpanded="True">
<Expander.Header>
<TextBlock FontSize="20" TextWrapping="Wrap" Margin="0,10,0,5" >
<Bold><TextBlock Text="{Binding Name}"/></Bold> - <TextBlock FontSize="20" Text="{Binding ItemCount}"/> logs
</TextBlock>
</Expander.Header>
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn
Header="event id"
Width="120"
DisplayMemberBinding="{Binding EventID}" />
<GridViewColumn
Header="level"
Width="160"
DisplayMemberBinding="{Binding Level}" />
<GridViewColumn
Header="server"
Width="160"
DisplayMemberBinding="{Binding Server}" />
<GridViewColumn
Header="log name"
Width="160"
DisplayMemberBinding="{Binding LogName}" />
<GridViewColumn
Header="source"
Width="240"
DisplayMemberBinding="{Binding Source}" />
<GridViewColumn
Header="logged"
Width="240"
DisplayMemberBinding="{Binding Logged}" />
</GridView>
</ListView.View>
</ListView>
But still the performance is not improving at all. I found an example using ListBox, but how to virtualize a ListView? I struggled quite a bit.
I heard that with grouping, the virtualization is turned off in previous version of WPF, but with .NET 4.5, WPF has a IsVirtualizingWhenGrouping property, I already set it to True.
Update: The culprit is custom styling, after removing it, the list view runs smoothly like butter
"UI virtualization stores only visible items in memory but in a data-binding scenario stores the entire data structure in memory. In contrast, data virtualization stores only the data items that are visible on the screen in memory."
"By default, UI virtualization is enabled for the ListView and ListBox controls when their list items are bound to data."
For more info view the original MSDN source.
This article will help you a lot.Also can see..
ListView UI virtualization
WPF Data virtualizing ListView
I know this is an old question but I came across it looking for an answer to my question and wanted to share what I discovered in case it's useful for anyone else. I had a very similar situation with a ListView control that was not virtualizing. I remove the custom style that I had on it (after reading this thread and associated links) and it started virtualizing correctly.
After much investigation, comparison to the default template, and narrowing down I figure out that it was the 'CanContentScroll' property on the ScrollContentPresenter inside that template. I had not set it at all, and when I set it to true it started virtualizing properly. I also noticed that the default template had 'CanHorizontallyScroll="False"' and 'CanVerticallyScroll="False"'; those didn't seem to make a difference that I could tell in my limited testing (I'm sure someone can chime in and say what they do) but I left them in anyway.
Here is my final style (note that this was started from default and modified, so not sure where the CanContentScroll property got dropped...):
<Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}"
TargetType="ScrollViewer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Margin="{TemplateBinding Padding}">
<ScrollViewer DockPanel.Dock="Top"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Focusable="false">
<GridViewHeaderRowPresenter Margin="2,0,2,0"
Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderContainerStyle="{Binding
Path=TemplatedParent.View.ColumnHeaderContainerStyle,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderTemplate="{Binding
Path=TemplatedParent.View.ColumnHeaderTemplate,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderTemplateSelector="{Binding
Path=TemplatedParent.View.ColumnHeaderTemplateSelector,
RelativeSource={RelativeSource TemplatedParent}}"
AllowsColumnReorder="{Binding
Path=TemplatedParent.View.AllowsColumnReorder,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderContextMenu="{Binding
Path=TemplatedParent.View.ColumnHeaderContextMenu,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderToolTip="{Binding
Path=TemplatedParent.View.ColumnHeaderToolTip,
RelativeSource={RelativeSource TemplatedParent}}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter"
KeyboardNavigation.DirectionalNavigation="Local"
CanContentScroll="True"
CanHorizontallyScroll="False"
CanVerticallyScroll="False"/>
</DockPanel>
<ScrollBar Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Value="{TemplateBinding HorizontalOffset}"
Style="{StaticResource StScrollBarNoMargin}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
<ScrollBar Name="PART_VerticalScrollBar"
Grid.Column="1"
Style="{StaticResource StScrollBarNoMargin}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Value="{TemplateBinding VerticalOffset}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Related
I am using AvalonDock in my application to have a Visual Studio look and feel. I would like to add some buttons and other controls to the header of the LayoutAnchorableControl as well as add some menu items to the drop down. I only want this to affect certain controls and not the entire layout.
I've been able to add buttons and controls to specific LayoutAnchorableControls by adding methods to the LayoutAnchorable that check for certain criteria and adding the controls to the theme. However, I feel there is a more robust solution I have yet to stumble on.
If you are using MVVM approach, you don't need to add methods to LayoutAnchorableControls. You can get it simply editing AvalonDock style.
For example, you may edit the LayoutDocumentTabItem style like the following:
<Style TargetType="{x:Type avalonDockControls:LayoutDocumentTabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type avalonDockControls:LayoutDocumentTabItem}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Following border is required to catch mouse events -->
<Border Grid.ColumnSpan="5" Background="Transparent" />
<TextBlock Grid.Column="0" Visibility="{Binding LayoutItem.Model.IsStatusQuadStringVisible,
RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BoolToVisibilityConverter}}"
Text="{Binding LayoutItem.Model.StatusQuadString,
RelativeSource={RelativeSource TemplatedParent}}" FontSize="{StaticResource SrkMainTouchControlFontSize}" HorizontalAlignment="Left" VerticalAlignment="Center" TextTrimming="CharacterEllipsis"/>
<ContentPresenter HorizontalAlignment="Center"
Grid.Column="2"
VerticalAlignment="Center"
Content="{Binding Model,
RelativeSource={RelativeSource TemplatedParent}}"
ContentTemplate="{Binding DocumentHeaderTemplate,
Mode=OneWay,
RelativeSource={RelativeSource AncestorType={x:Type avalonDock:DockingManager},
Mode=FindAncestor}}"
ContentTemplateSelector="{Binding DocumentHeaderTemplateSelector,
Mode=OneWay,
RelativeSource={RelativeSource AncestorType={x:Type avalonDock:DockingManager},
Mode=FindAncestor}}" />
<!-- region TabItem Buttons -->
<StackPanel Grid.Column="4" Orientation="Horizontal"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<Button Margin="2,0"
Command="{Binding LayoutItem.Model.MyCustomCommand, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ButtonAvalonDocumentStyleKey}">
<Button.ToolTip>
<PriorityBinding>
<Binding Path="LayoutItem.Model.MyCustomCommand" RelativeSource="{RelativeSource TemplatedParent}" IsAsync="True"/>
</PriorityBinding>
</Button.ToolTip>
<Path Data="{StaticResource SrkGeometryMyCustomCommand}" Stretch="Uniform" Margin="5,0" Style="{StaticResource PathAvalonDocumentStyleWithStrokeKey}" />
</Button>
</StackPanel>
<!-- endregion TabItem Buttons -->
</Grid>
</Border>
</Setter.Value>
</Setter>
</Style>
By doing this, you are adding a new custom Button to the tabbed Doc's title, binded to an ICommand named MyCustomCommand.
Furthermore, you may adding DataTrigger to the style binded to a Visibility property on the ViewModel that can handle button visibility, based on the business logic of your application.
I hope it helps.
I'm trying to create a list with fully functional headers, but I can only seem to get either a list with functional headers and all list view items reduced to textblocks. OR a list view with all the buttons and text fully styled, but without the headers being properly linked. See the image below;
My ListView definition looks like this for both of them:
<ListView ItemsSource="{Binding ScenarioComponents}" Style="{StaticResource ListViewWithHeader}" ItemContainerStyle="{StaticResource ListViewWithHeaderItem}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" Header="{Binding NameHeader}" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Width="Auto" Header="{Binding TypeHeader}" DisplayMemberBinding="{Binding Type}"/>
<GridViewColumn Width="Auto" Header="{Binding InfoHeader}"/>
<GridViewColumn Width="Auto" Header="{Binding ExportHeader}"/>
<GridViewColumn Width="Auto" Header="{Binding DeleteHeader}"/>
</GridView>
</ListView.View>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="1.5*"/>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding Name}" HorizontalAlignment="Left"/>
<Label Grid.Column="1" Content="{Binding Type}" Background="{StaticResource XVROrange}"/>
<Button Grid.Column="2" Style="{StaticResource BorderLessButton}" Command="{Binding MoreInfoCommand}">
<Button.Content>
<Image Source="/Views/Images/cc2_gui_information_default.png"/>
</Button.Content>
</Button>
<Button Grid.Column="3" Style="{StaticResource BorderLessButton}" Command="{Binding ExportCommand}">
<Button.Content>
<Image Source="/Views/Images/cc2_gui_export_default.png"/>
</Button.Content>
</Button>
<Button Grid.Column="4" Style="{StaticResource BorderLessButton}" Command="{Binding DeleteCommand}">
<Button.Content>
<Image Source="/Views/Images/cc2_gui_b_delete.png"/>
</Button.Content>
</Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And the only difference in the styling is that the one with the Headers working uses a GridViewRowPresenter in the ListViewItem like this:
<Style x:Key="ListViewWithHeaderItem" TargetType="ListViewItem">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border" Padding="0" Background="Transparent" BorderBrush="{StaticResource XVR70}" BorderThickness="1">
<GridViewRowPresenter Content="{TemplateBinding Content}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And the second one uses the same styling only with a ContentPresenter instead of the GridViewRowPresenter without any embellishments.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Background="Transparent" BorderBrush="{StaticResource Black47}" BorderThickness="0,0,0,0">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
For some reason using the GridViewRowPresenter means every item in my ListView.ItemTemplate's DataTemplate gets turned into a Textblock. And I can't figure out why. I'd really prefer to keep using the GridViewRowPresenter though as this means the headers are bound to the items in the list and scale with them and everything.
Has anyone got any idea how I can style this to work?
Can you put your templates from the ItemTemplate into the GridViewColumns?
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="Auto" Header="{Binding NameHeader}" DisplayMemberBinding="{Binding Name}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Grid.Column="0" Content="{Binding Name}" HorizontalAlignment="Left"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!-- more columns -->
</GridView.Columns>
</GridView>
</ListView.View>
i have problem with styling the combobox's togglebutton.
my combobox xaml code looks like this:
<ComboBox Width="Auto"
HorizontalContentAlignment="Stretch"
FontFamily="HelveticaNeue-Bold"
FontSize="20"
FontWeight="Bold"
Foreground="#FFC0C0C0"
Padding="0,0,0,0"
Style="{DynamicResource navigationComboBox}"
ItemsSource="{Binding Tournaments}"
SelectedValue="{Binding SelectedTournament}">
<ComboBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
</ComboBox.Resources>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"
Orientation="Vertical"
Width="auto"
Height="{Binding Tournaments, Converter={StaticResource CollectionToHeightConverter}}"/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.ItemTemplate>
<DataTemplate>
<DockPanel x:Name="comboDock">
<DockPanel.Background>
<ImageBrush ImageSource="{Binding Converter={StaticResource ImagePathConverter}, ConverterParameter=comboboxitem-line.png}" />
</DockPanel.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="41" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DockPanel x:Name="comboArrow"
Grid.Column="0"
Visibility="Collapsed">
<DockPanel.Background>
<ImageBrush ImageSource="{Binding Converter={StaticResource ImagePathConverter}, ConverterParameter=SportsSubMenuActive.png}" />
</DockPanel.Background>
</DockPanel>
<TextBlock x:Name="comboText"
Grid.Column="1"
FontFamily="HelveticaNeue-Bold"
FontSize="20"
FontWeight="Bold"
Foreground="#FFC0C0C0"
Padding="0,0,10,0"
Text="{Binding Path=Name}"
TextAlignment="Left"
TextWrapping="Wrap" />
</Grid>
</DockPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="True">
<Setter TargetName="comboArrow" Property="Visibility" Value="Visible" />
<Setter TargetName="comboText" Property="Foreground" Value="#F94B01" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
so i'm trying to remove the background set to on togglebutton, but it is not possible. if i remove the background on itemtemplate, then i can style the toggle button background. is there any special order in the process to prevent me from changing the background of the togglebutton content if it is set in itemtemplate?
thanks in advance guys,
Kristo
Setting a property directly takes priority over any Setter(s). Instead of setting the property directly, use a Style for your DockPanel and use a Setter to set the background similar to what you do in your DataTrigger. That should allow you to change the background property elsewhere.
I'm using theExpression Dark WPF Theme(http://wpfthemes.codeplex.com/) with a ListView(view property set to a GridView) to display some user data like the following :
<ListView
Grid.Row="1"
ItemsSource="{Binding RegisteredUsers}"
SelectedItem="{Binding SelectedUser}"
>
<ListView.View>
<GridView>
<GridViewColumn
Header="Login"
DisplayMemberBinding="{Binding Login}"
Width="60"/>
<GridViewColumn
Header="Full Name"
DisplayMemberBinding="{Binding FullName}"
Width="180"/>
<GridViewColumn
Header="Last logon"
DisplayMemberBinding="{Binding LastLogon}"
Width="120"/>
<GridViewColumn
Header="Photo"
Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image
Source="{Binding Photo}"
Width="30"
Height="35"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
The rows have white text with a dark background and white background when selected, however the text color doesnt change when selected and it makes very difficult to read, I would like the text to have a dark color when the row is selected. I have searched for a way to style the text color but with no success, here is the control template for the ListViewItem :
<Border SnapsToDevicePixels="true" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2" x:Name="border">
<Grid Margin="2,0,2,0">
<Rectangle x:Name="Background" IsHitTestVisible="False" Opacity="0.25" Fill="{StaticResource NormalBrush}" RadiusX="1" RadiusY="1"/>
<Rectangle x:Name="HoverRectangle" IsHitTestVisible="False" Opacity="0" Fill="{StaticResource NormalBrush}" RadiusX="1" RadiusY="1"/>
<Rectangle x:Name="SelectedRectangle" IsHitTestVisible="False" Opacity="0" Fill="{StaticResource SelectedBackgroundBrush}" RadiusX="1" RadiusY="1"/>
<GridViewRowPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="0,2,0,2" VerticalAlignment="Stretch" />
</Grid>
</Border>
The trigger that changes the background color simply applies an animation to change the 'SelectedRectangle' opacity, but I cant change the text color on the same trigger(I tried using a setter for the foreground color on the ListViewItem, but with no success).
Does someone have a clue on that?
Managed to solve by applying a textblock style on the GridViewRowPresenter scope :
<GridViewRowPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="0,2,0,2" VerticalAlignment="Stretch" >
<GridViewRowPresenter.Resources>
<Style
TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource {x:Type TextBlock}}"
>
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}}"
Value="True">
<Setter
Property="Foreground"
Value="Black"
/>
</DataTrigger>
</Style.Triggers>
</Style>
</GridViewRowPresenter.Resources>
</GridViewRowPresenter>
Try changing the TextBlock.Foreground
<GridViewRowPresenter TextBlock.Foreground="{TemplateBinding Foreground}"/>
Is it possible to disable the "Select all" button in the upper left corner of the WPF DataGrid?
There is a Property HeadersVisibility in DataGrid. It has four values - All, Column, Row, None.
With HeadersVisibility = All, you will get the SelectAll Button.
With HeadersVisibility = Column, you will get only Columns. Not the SelectAll Button or Row Headers to select a complete row.
With HeadersVisibility = Row, you will get only Row headers to select whole row. Not the SelectAll Button or Columns.
With HeadersVisibility = None, you will get nothing. All the headers will be hidden.
I hope this helps you.
After using Snoop to analyze the Visual Tree of a test app I put together, I came up with this solution using the DataGrid_Loaded event):
private void TheGrid_Loaded(object sender, RoutedEventArgs e) {
var dataGrid = (DataGrid)sender;
var border = (Border)VisualTreeHelper.GetChild(dataGrid, 0);
var scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
var grid = (Grid)VisualTreeHelper.GetChild(scrollViewer, 0);
var button = (Button)VisualTreeHelper.GetChild(grid, 0);
button.IsEnabled = false;
}
There may be a more elegant XAML only solution out there, but this is what came to mind first, and it seems to work well enough (I'm obviously not doing any Exception handling either).
Note: I haven't played around with disabling/re-enabling the DataGrid to make sure that the select all button stays disabled. If it doesn't stay disabled, then you may want to also hook into the DataGrid_IsEnabledChanged event.
Hope this helps!!
Add a commandbinding to the SelectAll Command and return false in the CanExecute to disable the selectall button.
see: Event for Select All: WPF Datagrid
If you don't need extended selection in your DataGrid (i.e. switch to single cell selection), you may set:
<DataGrid SelectionMode="Single">
It disables also SelectAll button in top-left corner.
Based on this answer, you can keep your headers and selection mode.
Inside the resources of your user control put :
<Style x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}"
TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<!-- an empty ControlTemplate is fine -->
<ControlTemplate TargetType="{x:Type Button}" />
</Setter.Value>
</Setter>
</Style>
With a little bit of more work, you can add a ToolTip to help the user to discover Ctrl and Shift.
<Style x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}"
TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<!-- an empty ControlTemplate is fine -->
<ControlTemplate TargetType="{x:Type Button}">
<DockPanel HorizontalAlignment="Center"
IsHitTestVisible="False"
VerticalAlignment="Center">
<TextBlock FontSize="18"
FontWeight="ExtraBlack"
Text="ⓘ"
TextAlignment="Center"
ToolTip="{StaticResource DataGridHowTo}" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
For the checkbox in the row headers see this post.
I would change the Control Template of DataGrid.
Needs to disable this button inside of template.
This is DataGrid ControlTemplate:
<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>
<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>
Disable the button it manually and assign this ControlTemplate to your DataGrid.