Extend LayoutAnchorable to have use its own style - c#

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.

Related

Binding Items collection on Menu to be shown on MenuItem Popup

I have the need to have a custom Menu (AMTMenu class inheriting Menu plus some additional DependencyProperties) with a MenuItem (a hamburger button actually) with dynamic children, since this menu is to be reused in a lot of layouts. Other than that, it should show other 5 TopLevel menu items that display info contained on the DataContext without any children attached and a refresh button. It's working fine except for the sub menu part which is not being shown when I click the hamburger MenuItem because I can't seem to bind the items correctly. Here's the code I have so far:
<Menu.Template>
<ControlTemplate>
<Grid Name="ContentGrid"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"
IsItemsHost="True">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="HamburgerButtonColumn" Width="5*" />
<ColumnDefinition x:Name="ButtonsColumn" Width="90*" />
<ColumnDefinition x:Name="RefreshButtonColumn" Width="5*"/>
</Grid.ColumnDefinitions>
<MenuItem Foreground="{DynamicResource BlackBrush}"
Focusable="False"
Template="{DynamicResource MainMenuButtonTemplate}">
<MenuItem.Icon>
<iconPacks:PackIconMaterial Kind="Menu"
HorizontalAlignment="Left"
VerticalAlignment="Center"
MinHeight="20" />
</MenuItem.Icon>
</MenuItem>
<UniformGrid Name="ButtonsUniformGrid"
Grid.Column="1"
Columns="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:AMTMenu}}, Path=ButtonCount}"
Rows="1"
HorizontalAlignment="Stretch">
<MenuItem Grid.Column="0"
Template="{DynamicResource OiButtonsTemplate}"
Foreground="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource OiMainMenuButtonsColorBrushConverter}}"
Focusable="False"
Command="{Binding ShowRefreshDataCommand}"
CommandParameter="Button1">
<MenuItem.Tag>
<MultiBinding Converter="{StaticResource MainMenuButtonsTextConverter}" ConverterParameter="INC">
[ ... MultiBinding logic ... ]
</MultiBinding>
</MenuItem.Tag>
</MenuItem>
[ ... XAML Code for the other 4 MenuItems ... ]
</UniformGrid>
<DockPanel Name="PART_Refresh"
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
[ ... XAML Code for the refresh button ... ]
</DockPanel>
</Grid>
</ControlTemplate>
</Menu.Template>
As for the hamburger MenuItem, I have the following template:
<ControlTemplate x:Key="MainMenuButtonTemplate"
TargetType="{x:Type MenuItem}">
<Grid SnapsToDevicePixels="true"
HorizontalAlignment="Stretch">
<StackPanel Background="{TemplateBinding Background}"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<ContentControl x:Name="PART_Button"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
Content="{TemplateBinding Icon}"
Focusable="False" />
</StackPanel>
<Popup x:Name="PART_Popup"
AllowsTransparency="true"
Focusable="false"
HorizontalOffset="1"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"
Placement="Bottom"
VerticalOffset="-1">
<Border BorderThickness="2"
BorderBrush="White"
Background="{TemplateBinding Background}">
<ScrollViewer x:Name="SubMenuScrollViewer"
CanContentScroll="true"
Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<ItemsPresenter x:Name="ItemsPresenter"
KeyboardNavigation.DirectionalNavigation="Cycle"
Grid.IsSharedSizeScope="true"
Margin="2"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource AccentColorBrush}" TargetName="PART_Button"/>
<Setter Property="Background" Value="{DynamicResource GrayBrush}" TargetName="PART_Button"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Finally, I'm declaring the Menu and submenu with the following XAML:
<local:AMTMenu x:Name="MainMenu"
DockPanel.Dock="Top"
DataContext="{Binding CurrentModel}"
IsButton1Visible="True"
IsButton2Visible="True"
IsButton3Visible="True"
IsButton4Visible="True"
IsButton5Visible="False">
<MenuItem Header="Item 1" />
<Separator />
<MenuItem Header="Item 2" />
<Separator />
<MenuItem Header="Item 3" />
</local:AMTMenu>
How can I bind the Items collection on the Menu to be shown on the hamburger MenuItem popup?
So I found the problem, posting here to help anyone who has a similar problem... The issue was that the hamburger MenuItem was declared on the template so, the Menu wasn't getting any children and consequentely not firing the IsSubmenuOpen property on the MenuItem. After I realized this, the solution was pretty simple, replaced the MenuItem on the Template with an ItemsPresenter and moved the MenuItem to the Menu content. Also, and since the Menu now has Items defined in its class, I can't declare the sub menu as I was doing previously, it would only replace my default item, so I had to use a new DependencyProperty called SubMenuItems.
Here's the final code:
AMTMenu.xaml
<Menu>
<Menu.Template>
<ControlTemplate>
<Grid Name="ContentGrid"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"
IsItemsHost="True">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="HamburgerButtonColumn" Width="5*" />
<ColumnDefinition x:Name="ButtonsColumn" Width="90*" />
<ColumnDefinition x:Name="RefreshButtonColumn" Width="5*"/>
</Grid.ColumnDefinitions>
<ItemsPresenter x:Name="ItemsPresenter"
HorizontalAlignment="Center"
VerticalAlignment="Center"
KeyboardNavigation.DirectionalNavigation="Cycle"
Grid.IsSharedSizeScope="true"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
KeyboardNavigation.TabNavigation="Cycle" />
<UniformGrid Name="ButtonsUniformGrid"
Grid.Column="1"
Columns="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:AMTMenu}}, Path=ButtonCount}"
Rows="1"
HorizontalAlignment="Stretch">
<MenuItem Grid.Column="0"
Template="{DynamicResource OiButtonsTemplate}"
Foreground="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource OiMainMenuButtonsColorBrushConverter}}"
Focusable="False"
Command="{Binding ShowRefreshDataCommand}"
CommandParameter="Button1">
<MenuItem.Tag>
<MultiBinding Converter="{StaticResource MainMenuButtonsTextConverter}" ConverterParameter="INC">
[ ... MultiBinding logic ... ]
</MultiBinding>
</MenuItem.Tag>
</MenuItem>
[ ... XAML Code for the other 4 MenuItems ... ]
</UniformGrid>
<DockPanel Name="PART_Refresh"
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
[ ... XAML Code for the refresh button ... ]
</DockPanel>
</Grid>
</ControlTemplate>
</Menu.Template>
<MenuItem Foreground="{DynamicResource BlackBrush}"
Focusable="False"
Template="{DynamicResource MainMenuButtonTemplate}"
AllowDrop="True"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:AMTMenu}, Path=SubMenuItems}">
<MenuItem.Icon>
<iconPacks:PackIconMaterial Kind="Menu" MinHeight="20" />
</MenuItem.Icon>
</MenuItem>
</Menu>
Menu declaration on parent View:
<local:AMTMenu x:Name="MainMenu"
DockPanel.Dock="Top"
DataContext="{Binding CurrentModel}"
IsButton1Visible="True"
IsButton2Visible="True"
IsButton3Visible="True"
IsButton4Visible="True"
IsButton5Visible="False">
<local:AMTMenu.SubMenuItems>
<local:SubMenuItemsCollection>
<MenuItem Header="Item 1" />
<Separator />
<MenuItem Header="Item 2" />
<Separator />
<MenuItem Header="Item 3" />
</local:SubMenuItemsCollection>
</local:AMTMenu.SubMenuItems>
</local:AMTMenu>
Where SubMenuItemsCollection is just a class that derives from ObservableCollection
public class SubMenuItemsCollection : ObservableCollection<FrameworkElement> { }
Hope this helps someone in the future ;)

Default behavior of a textbox

I've got a custom control that is a textbox and two buttons inside a frame.
I'd like the frame to display the typical textbox border-behaviour. Currently, it just has a black border. Is there a short way or will I need 200 lines of XAML?
(I've found some examples e.g. the ComboBoxStyles-Example from MS, but .. these do use 200 lines of XAML).
This is the style for the IntegerSpinControl:
<Style TargetType="{x:Type cc:IntegerSpinControl}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:IntegerSpinControl}">
<Border BorderThickness="1" BorderBrush="Black">
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
<Grid DockPanel.Dock="Right" x:Name="grid1"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<RepeatButton Grid.Row="0"
Grid.Column="1"
Width="22"
Height="10"
Padding="0"
BorderThickness="0"
Command="{x:Static cc:IntegerSpinControl.IncreaseCommand}">
<RepeatButton.Content>
<Rectangle Width="16"
Height="5"
Fill="{StaticResource brush.scroll.up}" />
</RepeatButton.Content>
</RepeatButton>
<RepeatButton Grid.Row="1"
Grid.Column="1"
Width="22"
Height="10"
Padding="0"
BorderThickness="0"
Command="{x:Static cc:IntegerSpinControl.DecreaseCommand}">
<RepeatButton.Content>
<Rectangle Width="16"
Height="5"
Fill="{StaticResource brush.scroll.down}" />
</RepeatButton.Content>
</RepeatButton>
</Grid>
<TextBox DockPanel.Dock="Left"
BorderThickness="0"
HorizontalAlignment="Stretch"
Grid.Row="0"
Grid.Column="0"
Width="Auto"
Margin="0,0,1,0"
VerticalAlignment="Center"
IsReadOnly="True"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=FormattedValue,
Mode=OneWay}" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
There is already a control in the Extended WPF Toolkit that might be what you are looking for:
IntegerUpDown Control
Maybe you can use that instead?
BTW: There are also a Decimal and a Double version in the toolkit.
That being said, if you have to use your own Custom Control you will have to create the Templates and Styles yourself, however you can probably copy heavily from the Windows defaults.

How to make a custom tool tip template in WPF XAML

I have a number of buttons on a form (devcomponents ButtonDropDown controls to be precise).
I want to show a tool tip for each that contains a header at the top, an image on the left and a description on the right.
The header needs to be tied to the ButtonDropDown.Header, the image to the ButtonDropDown.Image. I also then need to define the description somewhere.
I've only been using WPF for a few weeks so I've not managed to find any answers via searching, though I have studied a few.
Below is my attempt at creating a template that really doesn't work at all:
<Style TargetType="dcr:ButtonDropDown">
<Setter Property="OverridesDefaultStyle" Value="True"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dcr:ButtonDropDown">
<ContentControl>
<ContentControl.ToolTip>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Content="{TemplateBinding Header}" FontWeight="Bold" />
<Viewbox Grid.Row="1" Grid.Column="0" Width="64" Height="32" Margin="3">
<ContentControl Content="{TemplateBinding Image}" />
</Viewbox>
<Label Grid.Row="1" Grid.Column="1"
Content="{TemplateBinding ToolTip.Content}" />
</Grid>
</ContentControl.ToolTip>
</ContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I then define a button as follows:
<dcr:ButtonDropDown Header="-X" Command="{Binding MoveCommand}" CommandParameter="xMinus"
ImagePosition="Top" IsEnabled="{Binding UserConfiguration.Move.Visible}"
ToolTip="move x axis down">
<dcr:ButtonDropDown.Image>
<Viewbox Width="32" Height="32" Margin="3">
<ContentControl Content="{StaticResource minusXImage}" />
</Viewbox>
</dcr:ButtonDropDown.Image>
</dcr:ButtonDropDown>
Please could someone give me an idea how to go about this?
I've gone some way to answering this question.
The following style is defined for ToolTip:
<Style TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Header)}"
FontWeight="Bold" />
<Viewbox Grid.Row="1" Grid.Column="0" Width="64" Height="32" Margin="3">
<ContentControl Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Image)}" />
</Viewbox>
<Label Grid.Row="1" Grid.Column="1"
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.ToolTip)}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I then define a button as above and the ToolTip text and header appear in the ToolTipas required.
The key is the binding:
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Header)}"
Which finds the Tooltip as an ancestor of Label and casts its PlacementTarget into a ButtonDropDown
What doesn't work is the image. This appears in the ToolTip but is removed from the button.
This will also break any other controls' tooltips if they are not ButtonDropDown controls.
I'm beginning to think I'll need to create some custom controls that contain the information I require for the ToolTip for each control.

ContentControl Wrapping Issue

I am trying to create a Custom tooltip Control. This control is inherited from ToolTip class. My Custom Tooltip will have a header and a content area. Content could be normal text or any other content (Image, richtextbox etc). Following is the Template Style that custom tooltip control.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type customControls:FlyoutHelp}">
<Border BorderThickness="0" Margin="15" Width="300">
<Border.Effect>
<DropShadowEffect Opacity="0.7" />
</Border.Effect>
<StackPanel TextBlock.FontFamily="Trebuchet MS" TextBlock.FontSize='12'>
<TextBlock Background="{StaticResource DellBlue}" Height="23" Foreground="#FFFFFF" Padding="0,4,0,0" TextAlignment="Center" Text="{Binding HeaderText, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<Border Background="{StaticResource DellLightGrey}" TextBlock.Foreground="{StaticResource DarkestGrey}" Padding="8">
<ContentControl Content="{Binding HelpContent, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
</Border>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
Now as you can see in my template that I am using ContentControl for showing the content of the tooltip. The problem is when my HelpContent is just plain String, it doesn't wrap that text. I can't replace ContentControl with TextBlock because HelpContent could be some other type too (image, richtextbox etc). Can anyone please provide me what is the best way to fix this problem? I will be really very thankful.
Replace ContentControl tag with:
<ContentPresenter Content="{TemplateBinding HelpContent}">
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
[Note: you can leave it as a ContentControl, but ContentPresenter is lighter and follows conventions]
Change StackPanel to Grid since it doesn't know the width for it to wrap.
<Grid TextBlock.FontFamily="Trebuchet MS" TextBlock.FontSize='12'>
<Grid.RowDefinitions>
<RowDefinitions/>
<RowDefinitions/>
<Grid.RowDefinitions/>
<TextBlock Grid.Row="0" Background="{StaticResource DellBlue}" Height="23" Foreground="#FFFFFF" Padding="0,4,0,0" TextAlignment="Center" Text="{Binding HeaderText, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<Border Grid.Row="1" Background="{StaticResource DellLightGrey}" TextBlock.Foreground="{StaticResource DarkestGrey}" Padding="8">
<ContentControl Content="{Binding HelpContent, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
</Border>
</Grid>

How to disable the 'Select All' button of a DataGrid

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.

Categories

Resources