在这篇文章"access-scrollview-properties-of-a-datagrid-in-wpf" 的帮助下,我设法通过可视化树访问了datagrid 的scrollviewer。
但是,尽管检查了 scrollviewer 的多个属性,我还是找不到我要查找的内容。
所以,我最终自己计算了大小(datagrid 的宽度 - 冻结列的宽度)。我想我也会计算其他列的宽度来获得scrollviewer内内容的宽度...
这是一个在 Blend 中运行的简单示例(项目名称:GridScrollViewer):
MainWindow.xaml:
<Window x:Class="GridScrollViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:GridScrollViewer"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<DockPanel
LastChildFill="True"
Margin="10">
<StackPanel
Width="auto"
Orientation="Horizontal"
DockPanel.Dock="Bottom">
<TextBlock Text="Scrollviewer offset: "/>
<TextBlock Name="myScrollViewerOffsetText" Text=""/>
</StackPanel>
<StackPanel
Width="auto"
Orientation="Horizontal"
DockPanel.Dock="Bottom">
<TextBlock Text="Scrollviewer width?: "/>
<TextBlock Name="myScrollViewerText" Text=""/>
</StackPanel>
<StackPanel
Width="auto"
Orientation="Horizontal"
DockPanel.Dock="Bottom">
<TextBlock Text="Expected value for scrollviewer width: "/>
<TextBlock Name="myExpectedValueText" Text=""/>
</StackPanel>
<StackPanel
Width="auto"
Orientation="Horizontal"
DockPanel.Dock="Bottom">
<TextBlock Text="First four columns width: "/>
<TextBlock Name="myColumnsText" Text=""/>
</StackPanel>
<StackPanel
Width="auto"
Orientation="Horizontal"
DockPanel.Dock="Bottom">
<TextBlock Text="Datagrid width: "/>
<TextBlock Text="{Binding ElementName=myGrid, Path=ActualWidth}"/>
</StackPanel>
<DataGrid
ItemsSource="{Binding}"
Name="myGrid"
DockPanel.Dock="Top"
Margin="0,0,0,10"
FrozenColumnCount="4"
HorizontalScrollBarVisibility="Visible"
HeadersVisibility="Column"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserResizeColumns="True"
LayoutUpdated="myGrid_LayoutUpdated"
/>
</DockPanel>
MainWindow.xaml.cs:
using System;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace GridScrollViewer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
CreateDataGrid();
}
public void CreateDataGrid()
{
DataTable dt = new DataTable();
dt.Columns.Add("Col 1", typeof(string));
dt.Columns.Add("Col 2", typeof(string));
dt.Columns.Add("Col 3", typeof(string));
dt.Columns.Add("Col 4", typeof(string));
dt.Columns.Add("Col 5", typeof(int));
dt.Columns.Add("Col 6", typeof(int));
dt.Columns.Add("Col 7", typeof(int));
dt.Columns.Add("Col 8", typeof(int));
dt.Columns.Add("Col 9", typeof(int));
dt.Columns.Add("Col 10", typeof(int));
dt.Columns.Add("Col 11", typeof(int));
dt.Columns.Add("Col 12", typeof(int));
dt.Columns.Add("Col 13", typeof(int));
dt.Columns.Add("Col 14", typeof(int));
for (int i = 0; i < 10; i++)
{
dt.Rows.Add("First field",
"Second field",
"Third field",
"Fourth field",
100*i+i,
100 * i + i+1,
100 * i + i+2,
100 * i + i+3,
100 * i + i+4,
100 * i + i+5,
100 * i + i+6,
100 * i + i+7,
100 * i + i+8,
100 * i + i+9);
}
myGrid.DataContext = dt;
}
public void UpdatemyColumnsText()
{
double size = 0;
if (myGrid.Columns.Count > 4)
{
size = myGrid.Columns[0].ActualWidth
+ myGrid.Columns[1].ActualWidth
+ myGrid.Columns[2].ActualWidth
+ myGrid.Columns[3].ActualWidth;
}
myColumnsText.Text = ((int)size).ToString();
}
public void UpdateScrollViewerText()
{
ScrollViewer sc = (ScrollViewer)VisualTreeHelper.GetChild(
(VisualTreeHelper.GetChild(myGrid, 0)), 0);
myScrollViewerText.Text = "actual width: " + (int)sc.ActualWidth
+" - desired size: " + (int)sc.DesiredSize.Width
+" - render size: " + (int)sc.RenderSize.Width
+" - viewport: " + (int)sc.ViewportWidth;
myScrollViewerOffsetText.Text = ((int)sc.HorizontalOffset).ToString();
}
public void UpdateExpectedWidth()
{
double expectedWidth = 0;
if (myGrid.Columns.Count > 4)
{
expectedWidth = myGrid.ActualWidth -(myGrid.Columns[0].ActualWidth
+ myGrid.Columns[1].ActualWidth
+ myGrid.Columns[2].ActualWidth
+ myGrid.Columns[3].ActualWidth);
}
myExpectedValueText.Text = ((int)expectedWidth).ToString();
}
private void myGrid_LayoutUpdated(object sender, EventArgs e)
{
UpdatemyColumnsText();
UpdateScrollViewerText();
UpdateExpectedWidth();
}
}
}
这主要回答了我的问题,但如果有人有更好的选择,我很乐意阅读。