Вот то, что я придумал, используя VisualTreeHelper
.
Создайте метод, который может искать в Visual Tree дочерний элемент определенного типа.Я нашел метод для поиска родителя (обратное направление), который я смог изменить.https://stackoverflow.com/a/636456/1640271.
public static T FindVisualChild<T>(DependencyObject parent)
where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject childObject = VisualTreeHelper.GetChild(parent, i);
if (childObject == null) return null;
if (childObject is T obj)
{
return obj;
}
else
{
return FindVisualChild<T>(childObject);
}
}
return null;
}
Мой код включал создание одной константы, одной переменной класса и использование двух Window
триггеров событий.
Константа
(накладывает ограничение на ширину Window
, чтобы всегда была видна хотя бы некоторая часть вторых столбцов).
private const double _item2MinViewableWidth = 100;
Переменная
(используется для захвата Grid
из дерева визуалов, которое находится внутри ScrollView
DataGrid
).
private Grid _innerGrid;
События
private void Window_ContentRendered(object sender, EventArgs e)
{
_innerGrid = UIHelper.FindVisualChild<Grid>(dataGrid);
item2Column.MinWidth = _item2MinViewableWidth;
item1Column.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
item2Column.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
MaxWidth = ActualWidth;
_innerGrid.MinWidth = item1Column.ActualWidth + _item2MinViewableWidth;
_innerGrid.Width = item1Column.ActualWidth + _item2MinViewableWidth;
UpdateLayout();
var mainGridInitWidth = mainGrid.ActualWidth;
MinWidth = ActualWidth;
_innerGrid.Width = Double.NaN;
mainGrid.Width = mainGridInitWidth;
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.WidthChanged && _innerGrid != null)
{
var widthDetla = e.NewSize.Width - e.PreviousSize.Width;
mainGrid.Width += widthDetla;
}
if (Math.Abs(ActualWidth - MaxWidth) < 1)
{
dataGrid.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
}
else
{
dataGrid.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
}
}
Вот мой XAML для хорошей меры:
<Window
x:Class="WPFSandbox.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:local="clr-namespace:WPFSandbox"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Height="450"
ContentRendered="Window_ContentRendered"
ResizeMode="CanResize"
SizeChanged="Window_SizeChanged"
SizeToContent="Width">
<Grid x:Name="mainGrid">
<DataGrid x:Name="dataGrid"
AutoGenerateColumns="False"
CanUserResizeColumns="False"
HeadersVisibility="Column"
IsReadOnly="True"
ItemsSource="{Binding MyItems}">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter
Property="SeparatorVisibility"
Value="Hidden" />
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTextColumn x:Name="item1Column"
Binding="{Binding Item1}"
Header="Item1" />
<DataGridTextColumn x:Name="item2Column"
Binding="{Binding Item2}"
Header="Item2" />
</DataGrid.Columns>
</DataGrid>
</Grid>
Надеюсь, это соответствует тому, что вам нужно.