<Window x:Class="Gekka.WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Gekka.WpfApplication1"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="800" Width="800">
<Window.Resources>
<DataTemplate x:Key="pageItemTemplate">
<Grid Grid.Column="1" Margin="20" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Height="{Binding Path=ColumnHeader.ActualHeight}"
MouseLeftButtonDown="HeaderGrid_MouseLeftButtonDown"
MouseRightButtonUp="HeaderGrid_MouseRightButtonUp"
MouseMove="HeaderGrid_MouseMove">
<Grid.Background>
<VisualBrush Visual="{Binding}" Stretch="None"
AlignmentX="Left" AlignmentY="Top"
TileMode="None">
</VisualBrush>
</Grid.Background>
</Grid>
<Grid x:Name="grid" Grid.Row="1" Grid.RowSpan="2" ClipToBounds="True" Width="360" Height="300"
Tag="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Tag}">
<Grid.Background>
<VisualBrush Visual="{Binding}" Stretch="None"
AlignmentX="Left" AlignmentY="Top"
TileMode="None"
ViewboxUnits="Absolute"
ViewportUnits="RelativeToBoundingBox">
<VisualBrush.Viewbox>
<MultiBinding>
<MultiBinding.Converter>
<local:PageViewBoxConverter />
</MultiBinding.Converter>
<Binding ElementName="grid" Path="DataContext.ColumnHeader.ActualHeight" />
<Binding ElementName="grid" Path="ActualWidth" />
<Binding ElementName="grid" Path="ActualHeight" />
<Binding ElementName="grid" Path="Tag"/>
</MultiBinding>
</VisualBrush.Viewbox>
</VisualBrush>
</Grid.Background>
</Grid>
<Border Grid.Row="1" BorderBrush="{Binding BorderBrush}" BorderThickness="0,0,0,1" VerticalAlignment="Bottom"
SnapsToDevicePixels="True"/>
</Grid>
</DataTemplate>
<ContextMenu x:Key="ColumnContextMenu">
<MenuItem Header="Hide" Click="HideColumn_Click" />
<MenuItem Header="ShowAll" Click="ShowAllColumn_Click" />
</ContextMenu>
</Window.Resources>
<DockPanel>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<DockPanel>
<CheckBox x:Name="chkHide" IsChecked="True" Content="First Column Hide" DockPanel.Dock="Top"
Checked="chkHide_Checked" Unchecked="chkHide_Checked" FontSize="20" Margin="5"/>
<ScrollViewer Margin="5">
<!-- This DataGrid is target for VisualBrush -->
<local:DataGridEx x:Name="dg" AutoGenerateColumns="False"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
RowHeaderWidth="30" Width="400" HorizontalAlignment="Left"
TextElement.FontSize="20"
ItemsSource="{Binding}" DataContext="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789">
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="Column1" IsReadOnly="True"/>
<DataGridTextColumn Header="Column2" Binding="{Binding Mode=OneWay}" IsReadOnly="True"/>
</DataGrid.Columns>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="ContextMenu" Value="{StaticResource ColumnContextMenu}"/>
</Style>
</DataGrid.ColumnHeaderStyle>
</local:DataGridEx>
</ScrollViewer>
</DockPanel>
<Grid Grid.Column="1" >
<DocumentViewer>
<FixedDocument>
<PageContent>
<FixedPage Width="400" Height="400" >
<ContentPresenter Content="{Binding ElementName=dg}" ContentTemplate="{StaticResource pageItemTemplate}">
<ContentPresenter.Tag>
<sys:Int32>0</sys:Int32>
</ContentPresenter.Tag>
</ContentPresenter>
</FixedPage>
</PageContent>
<PageContent>
<FixedPage Width="400" Height="400" >
<ContentPresenter Content="{Binding ElementName=dg}" ContentTemplate="{StaticResource pageItemTemplate}">
<ContentPresenter.Tag>
<sys:Int32>1</sys:Int32>
</ContentPresenter.Tag>
</ContentPresenter>
</FixedPage>
</PageContent>
<PageContent>
<FixedPage Width="400" Height="400" >
<ContentPresenter Content="{Binding ElementName=dg}" ContentTemplate="{StaticResource pageItemTemplate}">
<ContentPresenter.Tag>
<sys:Int32>2</sys:Int32>
</ContentPresenter.Tag>
</ContentPresenter>
</FixedPage>
</PageContent>
</FixedDocument>
</DocumentViewer>
</Grid>
</Grid>
</DockPanel>
</Window>
namespace Gekka.WpfApplication1
{
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Globalization;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void chkHide_Checked(object sender, RoutedEventArgs e)
{
if (dg != null)
{
var chk = (CheckBox)sender;
if (chk.IsChecked == true)
{
this.dg.Columns[0].Visibility = Visibility.Visible;
}
else
{
this.dg.Columns[0].Visibility = Visibility.Collapsed;
}
}
}
private void HeaderGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.dg.TransformMouseLeftButtonDown(sender, e);
}
private void HeaderGrid_MouseMove(object sender, MouseEventArgs e)
{
this.dg.TransformMouseMove(sender, e);
}
private void HeaderGrid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
this.dg.TransformMouseRightButtonUp(sender, e);
}
private void HideColumn_Click(object sender, RoutedEventArgs e)
{
var mi=(MenuItem)sender;
if (mi.Parent is ContextMenu cm)
{
if (cm.PlacementTarget is DataGridColumnHeader header)
{
header.Column.Visibility = Visibility.Collapsed;
}
}
}
private void ShowAllColumn_Click(object sender, RoutedEventArgs e)
{
foreach (var column in this.dg.Columns)
{
column.Visibility = Visibility.Visible;
}
}
}
class DataGridEx : DataGrid
{
public DataGridEx()
{
this.Loaded += DagaGridEx_Loaded;
}
private void DagaGridEx_Loaded(object sender, RoutedEventArgs e)
{
var sv = this.Template.FindName("DG_ScrollViewer", this) as ScrollViewer;
this.ColumnHeader = sv?.Template.FindName("PART_ColumnHeadersPresenter", sv) as FrameworkElement;
}
public FrameworkElement ColumnHeader
{
get { return (FrameworkElement)GetValue(HeaderProperty); }
private set { SetValue(HeaderProperty, value); }
}
public static readonly DependencyProperty HeaderProperty
= DependencyProperty.Register(nameof(ColumnHeader), typeof(FrameworkElement), typeof(DataGridEx), new PropertyMetadata(null));
private bool TryGetControl<T>(Point pos, out T? thumb) where T : Control
{
thumb = null;
DependencyObject? d = this.InputHitTest(pos) as DependencyObject;
while (d != null && d != this)
{
thumb = d as T;
if (thumb != null)
{
return true;
}
if (d is Visual)
{
d = VisualTreeHelper.GetParent(d);
}
else
{
d = LogicalTreeHelper.GetParent(d);
}
}
return false;
}
private bool TryGetThumb(Point pos, out System.Windows.Controls.Primitives.Thumb? thumb)
{
return TryGetControl<System.Windows.Controls.Primitives.Thumb>(pos, out thumb);
}
public void TransformMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is FrameworkElement fe)
{
var pos = e.GetPosition(fe);
if (TryGetThumb(pos, out var thumb) && thumb.IsEnabled)
{
thumb.RaiseEvent(e);
e.Handled = true;
}
else if (this.InputHitTest(pos) is UIElement ui)
{
ui.RaiseEvent(e);
e.Handled = true;
}
}
}
public void TransformMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
if (sender is FrameworkElement fe)
{
var pos = e.GetPosition(fe);
DependencyObject? d = this.InputHitTest(pos) as DependencyObject;
while (d != null)
{
if (d is FrameworkElement fe2 && fe2.ContextMenu != null)
{
fe2.ContextMenu.PlacementTarget = fe2;
fe2.ContextMenu.IsOpen = true;
e.Handled = true;
return;
}
if (d is Visual)
{
d = VisualTreeHelper.GetParent(d);
}
else
{
d = LogicalTreeHelper.GetParent(d);
}
}
}
}
public void TransformMouseMove(object sender, MouseEventArgs e)
{
if (sender is FrameworkElement fe)
{
var pos = e.GetPosition(fe);
if (TryGetThumb(pos, out var thumb) && thumb.IsEnabled)
{
fe.Cursor = Cursors.SizeWE;
}
else
{
fe.Cursor = Cursors.Arrow;
}
}
}
}
class PageViewBoxConverter : System.Windows.Data.IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values != null && values.Length >= 4
&& values[0] is double headerHeight
&& values[1] is double boxWidth
&& values[2] is double boxHeight
&& values[3] is int page)
{
return new System.Windows.Rect(0, headerHeight + page * boxHeight, boxWidth, boxHeight);
}
return new Rect(0, 0, 0, 0);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
edit: Add Mouse Event on ColumnHeader