DataGrid нужна горизонтальная полоса прокрутки и возможность изменения размера - PullRequest
0 голосов
/ 17 января 2019

У меня есть DataGrid в ScrollViewer. У меня одна из двух проблем:

  1. Когда ширина сокращается и текст элемента обрезается (столбец H2 недостаточно широк), полоса прокрутки не отображается. Тем не менее, два моих столбца имеют соответствующий размер и не могут быть изменены вне экрана. XAML (в основном):

    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <DataGrid Width="{Binding ActualWidth, 
                      RelativeSource={RelativeSource AncestorType={x:Type ScrollViewer}}}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="H1" Width="40" MinWidth="35"/>
                <DataGridTextColumn Header="H2" Width="*" MinWidth="47"/>
            </DataGrid.Columns>
        </DataGrid>
    </ScrollViewer>
    
  2. Когда у меня есть рабочая полоса прокрутки, размеры столбцов могут быть изменены, так что правая может быть вне поля зрения (центральный разделитель может быть перемещен достаточно далеко вправо, чтобы весь столбец был вне поля зрения). XAML:

    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <Grid>
            <DataGrid Width="{Binding ActualWidth, 
                          RelativeSource={RelativeSource AncestorType={x:Type Grid}}}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="H1" Width="40" MinWidth="35"/>
                    <DataGridTextColumn Header="H2" Width="*" MinWidth="47"/>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </ScrollViewer>
    

(Примечание: в обоих случаях я исключил itemsource, так как не считаю, что это необходимо для вопроса, я могу добавить это, а также код бэкэнда, если необходимо).

Я полагаю, что это связано с элементом, с которым связан DataGrid (возможно, элемент Grid не изменяется должным образом, я попытался привязать ширину Grid к ScrollViewer но проблема такая же, как (1)). Я также заметил, что полоса прокрутки появляется (в обоих случаях), когда вертикальное содержимое обрезается и появляется вертикальная полоса прокрутки (оба появляются одновременно). Любые предложения, чтобы иметь полосу прокрутки и возможность убедиться, что столбцы не выходят за пределы экрана?

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Вот то, что я придумал, используя 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>

Надеюсь, это соответствует тому, что вам нужно.

0 голосов
/ 17 января 2019

Проблема в том, что ширина DataGrid привязана к ширине ScrollViewer

<DataGrid Width={Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}">

DataGrid никогда не будет шире ScrollViewer, поэтому полоса прокрутки не будет включена.

Если установить «Горизонтальное выравнивание» на «Растянуть», то получится макет, который, я думаю, вы ищете, и разрешить прокрутку. Таким образом, элемент DataGrid должен быть:

 <DataGrid HorizontalAlignment="Stretch">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="H1" Width="40" MinWidth="35"/>
                    <DataGridTextColumn Header="H2" Width="*" MinWidth="47"/>
                </DataGrid.Columns>
            </DataGrid>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...