Подтвердить что ты не робот

Изменить порядок масштабирования WPF

У меня есть приложение WPF, которое должно быть восприимчивым. Я хочу иметь DataGrid внутри Grid. Когда окно масштабируется, я хочу сначала изменить размер Grid, а затем DataGrid. Вот что я сделал до сих пор:

введите описание изображения здесь

В gif сверху вы можете видеть, что сначала изменяется размер Grid, и когда он достигает минимального размера масштабирования, он переходит в нижнее DataGrid. Не совсем то, что я хочу, потому что я хочу сначала масштабировать макет, а затем показывать полосу прокрутки в DataGrid вместо того, чтобы макет просто переходил на нее. Поэтому я попробовал следующее:

введите описание изображения здесь

Здесь вы можете видеть, что он показывает полосы прокрутки, как я хочу. Единственное, что он сначала изменяет размер DataGrid, и когда он изменил размер DataGrid, он начинает изменять размер сетки. Я хочу, чтобы это было наоборот, сначала измените размер сетки, затем измените размер DataGrid и покажите полосы прокрутки. Поэтому в основном я ищу решение, которое делает следующее:

  • Масштабируйте окно, которое масштабирует сетку.
  • Масштабировать сетку до минимального размера.
  • Когда он достиг минимального размера и все еще становится меньше, покажите полосу прокрутки в DataGrid.

Итак, это сводится к первому Gif из этого вопроса, за которым следуют полосы прокрутки в DataGrid

Есть ли способ сделать это? Похоже, я очень близок, потому что это комбинация этих двух вещей, но я не знаю, как это сделать. Здесь мой код:

<Grid Grid.Row="1" HorizontalAlignment="Right"  Grid.Column="0">
  <Grid ShowGridLines="False">
    <Grid.RowDefinitions>
      <RowDefinition MaxHeight="50"/>
      <RowDefinition Height="auto"/>
      <RowDefinition MaxHeight="20"/>
      <RowDefinition Height="auto"/>
      <RowDefinition MaxHeight="5"/>
      <RowDefinition Height="auto"/>
      <RowDefinition MaxHeight="5"/>
      <RowDefinition Height="auto"/>
      <RowDefinition MaxHeight="5"/>
      <RowDefinition Height="auto"/>
      <RowDefinition MaxHeight="50"/>
      <RowDefinition Height="auto"/>
      <RowDefinition MaxHeight="50"/>
      <RowDefinition Height="auto"/>
      <RowDefinition MaxHeight="5"/>
      <RowDefinition Name="DataGridRow" Height="*" MaxHeight="240" />
    </Grid.RowDefinitions>

    <Label Grid.Row="1" FontSize="24">Test</Label>
    <Label Grid.Row="3" Content="Test"/>
    <ComboBox Grid.Row="5" MaxWidth="500" MinWidth="300" HorizontalAlignment="Left"  />
    <Label Grid.Row="7" Content="Test"/>
    <ComboBox Grid.Row="9" MaxWidth="500" MinWidth="300" HorizontalAlignment="Left"/>
    <Separator Grid.Row="11"/>

    <Label Grid.Row="13" Content="Test" />
    <Grid Grid.Row="15">
      <DataGrid
          RowHeight="40"
           CanUserAddRows="False"
            x:Name="dataGrid"
            AutoGenerateColumns="False"
            CanUserResizeColumns="True"
            HeadersVisibility="None"
            GridLinesVisibility="None"
            ScrollViewer.CanContentScroll="True"
            ScrollViewer.VerticalScrollBarVisibility="Visible"
            ScrollViewer.HorizontalScrollBarVisibility="Auto"
        <DataGrid.Columns>
          <DataGridTextColumn IsReadOnly="True" Width="*" Binding="{Binding Name}">
            <DataGridTextColumn.ElementStyle>
              <Style TargetType="TextBlock">
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="Margin" Value="2,0,0,0"/>
              </Style>
            </DataGridTextColumn.ElementStyle>
          </DataGridTextColumn>
        </DataGrid.Columns>
      </DataGrid>
    </Grid>
  </Grid>
</Grid>
4b9b3361

Ответ 1

В тех случаях, когда решение уравнения компоновки больше не возможно со стандартными строительными блоками, вы можете сами делайте расчеты. Позволяя конвертеру вычислить оставшееся свободное пространство.

Оставшаяся проблема двоичная:

  • DataGrid может сокращаться только тогда, когда строки с размерами звезды ActualHeight 0.

    Решение: DataGrid.Style, который устанавливает dataGrid.MaxHeight, когда triggerGrid.ActualHeight= 0 (triggerGrid занимает размер звезды строка).

  • Когда мы даем MinHeight до DataGridRow, он не будет сокращаться, когда dataGrid.ActualHeight сжимается (он крадет высоту усадки назад).

    Решение: RowDefinition.Style, которое устанавливает его MinHeight в dataGrid.ActualHeight, когда triggerGrid.ActualHeight= 0 и фиксированное значение в противном случае.

Я установил цвета Controls BackGround, чтобы проиллюстрировать, когда высота размера звезды (оставшееся пустое пространство) становится равной 0.

<Window 

    ...

    Width="200" Height="450">
    <Window.Resources>
        <local:HeightConverter x:Key="HeightConverter" />
        <local:IsEqualToZeroConverter x:Key="IsEqualToZeroConverter" />
    </Window.Resources>
    <!--MainGrid-->
    <Grid x:Name="mainGrid">
        <Grid ShowGridLines="False">
            <Grid.RowDefinitions>
                <RowDefinition MaxHeight="50"/>
                <RowDefinition Height="auto"/>
                <RowDefinition MaxHeight="20"/>
                <RowDefinition Height="auto"/>
                <RowDefinition MaxHeight="5"/>
                <RowDefinition Height="auto"/>
                <RowDefinition MaxHeight="5"/>
                <RowDefinition Height="auto"/>
                <RowDefinition MaxHeight="5"/>
                <RowDefinition Height="auto"/>
                <RowDefinition MaxHeight="50"/>
                <RowDefinition Height="auto"/>
                <RowDefinition MaxHeight="50"/>
                <RowDefinition Height="auto"/>
                <RowDefinition MaxHeight="5"/>
                <RowDefinition x:Name="dataGridRow" Height="Auto">
                    <RowDefinition.Style>
                        <Style TargetType="{x:Type RowDefinition}">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding ActualHeight, ElementName=triggerGrid, Converter={StaticResource IsEqualToZeroConverter}}" Value="True">
                                    <Setter  Property="MinHeight" Value="{Binding ActualHeight, ElementName=dataGrid}"/>
                                </DataTrigger>
                                <DataTrigger Binding="{Binding ActualHeight, ElementName=triggerGrid, Converter={StaticResource IsEqualToZeroConverter}}" Value="False">
                                    <Setter  Property="MinHeight" Value="80.0"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </RowDefinition.Style>
                </RowDefinition>
            </Grid.RowDefinitions>
            <Label x:Name="bigLabel" Grid.Row="1" FontSize="24" Background="LightGray">Test</Label>
            <Label x:Name="regularLabel" Grid.Row="3" Content="Test" Background="LightGray"/>
            <ComboBox x:Name="comboBox" Grid.Row="5" MaxWidth="500" MinWidth="300" HorizontalAlignment="Left"  Background="LightGray" />
            <Label Grid.Row="7" Content="Test" Background="LightGray"/>
            <ComboBox Grid.Row="9" MaxWidth="500" MinWidth="300" HorizontalAlignment="Left" Background="LightGray"/>
            <Separator x:Name="separator" Grid.Row="11"/>
            <Label Grid.Row="13" Content="Test"  Background="LightGray"/>
            <!--TriggerGrid-->
            <Grid Grid.Row="14" x:Name="triggerGrid"/>
            <Grid Grid.Row="15">
                <DataGrid
                    x:Name="dataGrid"
                    RowHeight="40"
                    CanUserAddRows="False"
                    AutoGenerateColumns="False"
                    CanUserResizeColumns="True"
                    HeadersVisibility="None"
                    GridLinesVisibility="None"
                    ScrollViewer.CanContentScroll="True"
                    ScrollViewer.VerticalScrollBarVisibility="Visible"
                    ScrollViewer.HorizontalScrollBarVisibility="Auto">
                    <DataGrid.Style>
                        <Style TargetType="{x:Type DataGrid}">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding ActualHeight, ElementName=triggerGrid}" Value="0">
                                    <Setter Property="MaxHeight">
                                        <Setter.Value>
                                            <MultiBinding Converter="{StaticResource HeightConverter}">
                                                <Binding ElementName="mainGrid" Path="ActualHeight"/>
                                                <Binding ElementName="bigLabel" Path="ActualHeight"/>
                                                <Binding ElementName="regularLabel" Path="ActualHeight"/>
                                                <Binding ElementName="comboBox" Path="ActualHeight"/>
                                                <Binding ElementName="separator" Path="ActualHeight"/>
                                            </MultiBinding>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </DataGrid.Style>
                    <DataGrid.Columns>
                        <DataGridTextColumn IsReadOnly="True" Width="*" Binding="{Binding Name}">
                            <DataGridTextColumn.ElementStyle>
                                <Style TargetType="TextBlock">
                                    <Setter Property="VerticalAlignment" Value="Center" />
                                    <Setter Property="Margin" Value="2,0,0,0"/>
                                </Style>
                            </DataGridTextColumn.ElementStyle>
                        </DataGridTextColumn>
                    </DataGrid.Columns>
                </DataGrid>
            </Grid>
        </Grid>
    </Grid>
</Window>

Конвертеры

public class HeightConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        // only 1 check at startup (Debugging)
        if ((double)values[1] == 0.0) return 0.0;

        double mainGridHeight       = (double)values[0];
        double bigLabelHeight       = (double)values[1];
        double regularLabelHeight   = (double)values[2];
        double comboBoxHeight       = (double)values[3];
        double separatorHeight      = (double)values[4];

        double dataGridHeight = mainGridHeight - bigLabelHeight - 2 * (regularLabelHeight + comboBoxHeight) - regularLabelHeight - separatorHeight;

        if (dataGridHeight > 0.0) return dataGridHeight; else return 0.0;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public class IsEqualToZeroConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((double)value == 0.0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Ответ 2

Это не точный ответ. Но, это даст идею для достижения ваших потребностей.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />            
        <RowDefinition Height="5" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <DockPanel>                        
        <TextBlock DockPanel.Dock="Bottom" Grid.Row="1" FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" MaxHeight="240">DataGrid</TextBlock>
        <Separator DockPanel.Dock="Bottom"/>
        <TextBlock DockPanel.Dock="Bottom" FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">Top</TextBlock>
    </DockPanel>
    <GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" />
    <TextBlock Grid.Row="2" FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">Bottom</TextBlock>
</Grid>

Надеюсь, что это поможет.