在WPF中包装面板

时间:2011-03-04 20:21:54

标签: wpf xaml

我的窗口中有以下布局:

  1. Grid有两列
  2. GridSplitter调整网格列的大小
  3. 第二个网格列填充了StackPanel
  4. StackPanel垂直定位,有2个孩子:TextBlockWrapPanel
  5. WrapPanel有两个Grid s作为孩子
  6. 第一个Grid子项包含一个Image
  7. 第二个Grid包含一个垂直方向为3 TextBlock的StackPanel。
  8. 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>
    

    窗口打开后,第二列足够宽,可以将网格GridForImageGirdForText水平放置在一起。如果我使用网格分割器缩小第二列的宽度,GridForText网格会在GridForImage下面的某个位置放置,这是非常期待的。

    这就是我想要实现的目标:

    1. 我希望GridForText将其宽度缩小到一定的大小并保持定位在GridForImage的右侧,因为我将网格分割器移动到窗口的右侧。然后,当宽度缩小到某个值(例如200px)时,它应该放在GridForImage下面,即WrapPanel应该发挥它的魔力。现在,GridForText根本没有调整大小,当它的当前宽度对于WrapPanel的宽度变得太大时,它就会被放置在下面。
    2. GridForText放在GridForImage下方时,我希望GridForImage填充WrapPanel宽度的整个宽度。
    3. 这一切是否可行,我该怎么办?谢谢你们。

1 个答案:

答案 0 :(得分:1)

您实际上是在尝试使用两种不同的布局模式,因此您只需要在布局中设置两种不同的状态,然后添加绑定或触发器,以便在您想要切换模式时切换它们(即宽度) = 200)。使用网格是最灵活的,并且您可以更好地控制相对大小,但需要更多设置,并且在ControlTemplate或DataTemplate中最有效,您可以根据条件使用触发器一次设置一堆内容。 / p>

这是一个使用UniformGrid与一些Bindings和转换器的更紧凑的例子。我删除了图像上的固定大小 - 如果您更关心填充宽度而不是宽高比,请尝试Stretch =“Fill”。我还将一个StackPanel更改为DockPanel以保持其子项的垂直拉伸,并为其中一个TextBlock添加了一个Background,以显示它实际获得的宽度:

<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();
    }
}