Упаковочные панели в WPF - PullRequest
0 голосов
/ 04 марта 2011

У меня есть следующее расположение в моем окне:

  1. Grid с двумя столбцами
  2. GridSplitter, который изменяет размеры столбцов сетки
  3. Второй столбец сеткизаполнено StackPanel
  4. StackPanel ориентировано вертикально и имеет 2 детей: TextBlock и WrapPanel
  5. WrapPanel имеет двух Grid s как детей
  6. Первый Grid дочерний содержит один Image
  7. Второй Grid содержит StackPanel с 3 TextBlock s, ориентированными вертикально.

Код XAML выглядит следующим образом:

<Window>
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Left" />
    <StackPanel Grid.Column="1" Margin="5,0,0,0" Orientation="Vertical" 
        HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
      <TextBlock Text="Now here's a silly poem for you." />
      <WrapPanel>
        <Grid Name="GridForImage">
          <Image Width="200" Height="200" Source="Image.jpg" />
        </Grid>
        <Grid Name="GridForText">
          <StackPanel Orientation="Vertical">
            <TextBlock TextWrapping="WrapWithOverflow" Text="Roses are red." />
            <TextBlock TextWrapping="WrapWithOverflow" Text="Violets are blue." />
            <TextBlock TextWrapping="WrapWithOverflow" Text="You belong in a zoo." />
          </StackPanel>
        </Grid>
      </WrapPanel>
    </StackPanel>
  </Grid>
</Window>

Как только окно открывается, второй столбец становится достаточно широким, чтобы можно было размещать сетки GridForImage и GirdForText следующимдруг к другу по горизонтали.Если я уменьшу ширину второго столбца с помощью разделителя сетки, сетка GridForText будет помещена под GridForImage в одной точке, что вполне ожидаемо.

Вот чего я хотел бы достичь:

  1. Я хочу, чтобы GridForText сократил его ширину до определенного размера и оставался в положении справа от GridForImage, так какЯ перемещаю разделитель сетки в правую часть окна.Затем, когда ширина уменьшается до определенного значения, скажем, 200px, оно должно располагаться под GridForImage, то есть WrapPanel должно творить чудеса.Прямо сейчас, GridForText не меняет размер вообще, он просто помещается внизу, когда его текущая ширина становится слишком большой для ширины WrapPanel.
  2. Когда GridForText окажется под GridForImage, я хочу, чтобы GridForImage заполнил всю ширину WrapPanel.

Возможно ли все это и что мне делать?Спасибо вам всем.

1 Ответ

1 голос
/ 05 марта 2011

По сути, вы пытаетесь использовать два разных режима макета, поэтому вам просто нужно установить два разных состояния в вашем макете, а затем добавить привязки или триггеры для переключения между ними в точке, когда вы хотите переключить режимы (то есть ширину). = 200). Использование Grid является наиболее гибким и дает вам гораздо больший контроль над относительными размерами, но требует больше настроек и будет работать лучше всего в ControlTemplate или DataTemplate, где вы можете использовать триггеры для одновременной установки нескольких вещей на основе условия.

Вот более компактный пример использования UniformGrid с некоторыми привязками и конвертером. Я удалил фиксированный размер изображения - попробуйте Stretch = "Fill", если вам важнее ширина заливки, чем соотношение сторон. Я также изменил одну StackPanel на DockPanel, чтобы поддерживать вертикальное растяжение для его дочерних элементов, и добавил фон в один из TextBlocks просто для того, чтобы показать, какую ширину он действительно получает:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Left" />
    <DockPanel Grid.Column="1" Margin="5,0,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <TextBlock Text="Now here's a silly poem for you." DockPanel.Dock="Top"/>
        <UniformGrid Rows="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={x:Static local:LayoutModeConverter.Row}, ConverterParameter=200}"
                     Columns="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={x:Static local:LayoutModeConverter.Column}, ConverterParameter=200}">
            <Image Source="Image.jpg" />

            <StackPanel Orientation="Vertical">
                <TextBlock TextWrapping="WrapWithOverflow" Text="Roses are red." Background="Red" />
                <TextBlock TextWrapping="WrapWithOverflow" Text="Violets are blue." />
                <TextBlock TextWrapping="WrapWithOverflow" Text="You belong in a zoo." />
            </StackPanel>
        </UniformGrid>
    </DockPanel>
</Grid>

И конвертер:

public class LayoutModeConverter : IValueConverter
{
    public static readonly LayoutModeConverter Row = new LayoutModeConverter { RowMode = true };
    public static readonly LayoutModeConverter Column = new LayoutModeConverter { RowMode = false };

    public bool RowMode { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double width = System.Convert.ToDouble(value);
        double targetWidth = System.Convert.ToDouble(parameter);
        if (RowMode)
            return width > targetWidth ? 1 : 2;
        else
            return width > targetWidth ? 2 : 1;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...