有没有一种方法可以使GridSplitter不将元素推出窗口?

8

在下面的XAML中,当我将GridSplitter向左拖动时,它会将元素推出窗口。如何使所有元素都保持在窗口框架内?

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
    </Grid.ColumnDefinitions>

    <Button Grid.Column="0" Content="0" />
    <Button Grid.Column="1" Content="1" />
    <Button Grid.Column="2" Content="2" />
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Left" />
</Grid>

谢谢


尝试为GridColumnDefinitions设置MinWidth - Nitesh
感谢您的回复。我尝试过这种方法,但没有成功。我还尝试使用*大小的列,但没有结果。当我将窗口大小更改为其内容大小时,控件仍保留在窗口框架内,但窗口大小会发生变化。理想情况下,我希望窗口大小固定,而所有其他大小都是自动调整/按比例调整的。 - elm
3个回答

8
我知道解决你的问题的唯一方法是将网格分隔器左右两侧的列宽度属性设置为Width="*",并给网格分隔器一个独立的列,并将其水平对齐设置为HorizontalAlignment="Stretch"。你的代码应该像这样:
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="auto"/>
    </Grid.ColumnDefinitions>

    <Button Grid.Column="0" Content="0" />
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch"/>
    <Button Grid.Column="2" Content="1" />
    <Button Grid.Column="3" Content="2" />
</Grid>  

2
我遇到了同样的问题,并想出了这个解决方案。基本上,思路是在网格/列更改时动态更改相应列的MaxWidth。我在这里展示了两列,但我已经成功地使用了三列。
使用这种方法,如果将窗口调整为不再适合网格内容,网格将停止改变大小,因此ResizeGrid_SizeChanged事件将停止被调用。为了解决这个问题,您还可以监听窗口(或用户控件)大小更改事件。您可能还需要适当地绑定网格的MaxWidth,或者直接使用控件大小,如果您的网格填充窗口/用户控件的话。我在这里展示了如何通过XAML绑定MaxWidth属性。如果你不想这样做,你可以在窗口代码后面用"ActualWidth"替换"ResizeGrid.MaxWidth",并删除"ResizeGrid"对象上的"MaxWidth"绑定。
XAML:
<Window x:Class="App.Window1"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:Default="clr-namespace:App" 
        mc:Ignorable="d"
        SizeChanged="Window_SizeChanged"
        Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid x:Name="ResizeGrid" SizeChanged="ResizeGrid_SizeChanged" 
              MaxWidth="{Binding ActualWidth, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Default:Window1}}}">

            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="C0" Width="150" MinWidth="50" />
                <ColumnDefinition Width="5" />
                <ColumnDefinition x:Name="C2" Width="*" MinWidth="50" />
            </Grid.ColumnDefinitions>

            <Grid Grid.Column="0" Background="Green">
                <Label Content="Left" />
                <Label Content="Right" HorizontalAlignment="Right" />
            </Grid>

            <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" DragCompleted="GridSplitter_DragCompleted" />

            <Grid Grid.Column="2" Background="Red">
                <Label Content="Left" />
                <Label Content="Right" HorizontalAlignment="Right" />
            </Grid>
        </Grid>
    </Grid>
</Window>

C# 代码后台

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
    UpdateGridSplitterWidths();
}

private void ResizeGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
    UpdateGridSplitterWidths();
}

private void GridSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
    UpdateGridSplitterWidths();
}

private void UpdateGridSplitterWidths()
{
    C0.MaxWidth = Math.Min(ResizeGrid.ActualWidth, ResizeGrid.MaxWidth) - (C2.MinWidth + 5);
}

1

补充一下@Joseph的答案,他指引了我正确的方向。当你将“*”分数化或包含最小/最大宽度时,它仍然有效。

<Grid>
<Grid.ColumnDefinitions>
    <ColumnDefinition Width="0.35*"
                      MinWidth="48" />
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="*"
                      MaxWidth="48" />
</Grid.ColumnDefinitions>

这使您可以根据意图设置每列的初始宽度,并提供不将内容推出屏幕的功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接