让窗口基于一个控件的大小而不是其他控件的大小增长

时间:2017-06-30 10:54:19

标签: c# wpf

我有一个窗口包含一个带有可变文本的文本块和一个包含可变数量按钮的stackpanel。 My Window 当堆栈面板的宽度增加但让文本始终适应可用宽度时(当文本变长时不会使窗口宽度增大),如何让窗口在宽度上(水平方向)增长。

我尝试过使用和不使用Width =" Auto" / VerticalAlign =" Stretch" / TextWrapping等,但如果其中任何一个(文本长度/ stackpanel子项)的宽度增加,我只会获得增长的窗口。

我希望文本根据窗口的宽度进行换行,窗口宽度应基于stackpanel的宽度。 XAML只会很好。

修改

根据要求提供一些精简标记来重现问题:

<Window 
    Width="500" 
    Height="225" 
    MinWidth="500" 
    MinHeight="225"
    HorizontalAlignment="Stretch"
    SizeToContent="WidthAndHeight"
    ResizeMode="NoResize">

    <Grid HorizontalAlignment="Stretch" Width="Auto">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="35"/>
        </Grid.RowDefinitions>

        <!-- Text should adapt to the available width but not grow the window. Instead it should scroll vertically -->
        <ScrollViewer Grid.Row="0" Margin="15" VerticalScrollBarVisibility="Auto">
            <TextBlock TextWrapping="Wrap" Height="Auto">...Some Binding...</TextBlock>
        </ScrollViewer>

        <!-- Should be as wide as it needs to be, growing the window in width if neccessary -->
        <StackPanel x:Name="ButtonStackPanel" Grid.Row="1" FlowDirection="RightToLeft" Orientation="Horizontal" Width="Auto">
            ...Some Buttons...
        </StackPanel>
    </Grid>
</Window>

编辑2 该窗口的MinWidth应为500,如果stackpanel中只有一个按钮,它仍然应该拉伸全宽(500px)。

编辑3 - 更多图片

正确 - 文字很短,只有一个按钮 - &gt; MinWidth 500 enter image description here 错误 - 文本很长,应该在MinWidth为500时换行,因为只允许Stackpanel在宽度上增长窗口 enter image description here 正确 - 短文本但堆栈面板增长窗口 enter image description here

2 个答案:

答案 0 :(得分:3)

您必须将Width的{​​{1}}绑定到外部Window Grid(正如Mighty Badaboom建议的那样)和Width Width ScrollViewer ActualWidth的{​​{1}}。

以下是如何实现目标:

StackPanel

代码背后:

<Window SizeChanged="MainWindow_OnSizeChanged" Height="225" SizeToContent="Width" ResizeMode="NoResize">
<Grid Name="OuterGrid" MinWidth="500">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="35"/>
    </Grid.RowDefinitions>


    <ScrollViewer Grid.Row="0" Margin="15" VerticalScrollBarVisibility="Auto">
        <TextBlock TextWrapping="Wrap" Height="Auto">...Some Binding...</TextBlock>
    </ScrollViewer>

    <StackPanel Grid.Row="1" HorizontalAlignment="Stretch" Background="Blue">
        <StackPanel x:Name="ButtonStackPanel" HorizontalAlignment="Center" Grid.Row="1" FlowDirection="RightToLeft" Orientation="Horizontal" Width="Auto">
            ...Some Buttons...
        </StackPanel>
    </StackPanel>
</Grid>
</Window>


编辑:添加外部private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e) { if (e.WidthChanged) OuterGrid.Width = Panel.ActualWidth; } 以支持拉伸&amp;蓝色背景要求。

编辑2:您似乎无法实现仅使用XAML描述的行为。虽然修复了几行代码。

答案 1 :(得分:2)

您可以编写自己的自定义控件,并以宽度和高度由不同子元素支配的方式覆盖度量/排列。注意我在这里作弊有点只是使用面板的前两个孩子并根据你的问题赋予它们不同的含义,甚至不用先检查有效的子索引等。:

public class SizeAwareControl : Panel
{
    private UIElement HeightDeterminingContent
    {
        get { return InternalChildren[0]; }
    }
    private UIElement WidthDeterminingContent
    {
        get { return InternalChildren[1]; }
    }

    protected override Size MeasureOverride(Size constraint)
    {
        Size result = new Size(double.PositiveInfinity, double.PositiveInfinity);

        WidthDeterminingContent.Measure(result);

        result.Width = WidthDeterminingContent.DesiredSize.Width;

        HeightDeterminingContent.Measure(result);

        result.Height = WidthDeterminingContent.DesiredSize.Height + HeightDeterminingContent.DesiredSize.Height;

        return result;
    }
    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        HeightDeterminingContent.Arrange(new Rect(0, 0, WidthDeterminingContent.DesiredSize.Width, HeightDeterminingContent.DesiredSize.Height));
        WidthDeterminingContent.Arrange(new Rect(0, HeightDeterminingContent.DesiredSize.Height, WidthDeterminingContent.DesiredSize.Width, WidthDeterminingContent.DesiredSize.Height));
        return new Size(WidthDeterminingContent.DesiredSize.Width, WidthDeterminingContent.DesiredSize.Height + HeightDeterminingContent.DesiredSize.Height);
    }
}

用法

<local:SizeAwareControl>
    <!-- First child determines the height -->
    <ScrollViewer Margin="15" VerticalScrollBarVisibility="Auto" MaxHeight="600">
        <TextBlock TextWrapping="Wrap" Height="Auto">...Some Binding...</TextBlock>
    </ScrollViewer>
    <!-- Second child determines the width -->
    <StackPanel x:Name="ButtonStackPanel" Orientation="Horizontal" MinWidth="500">
        <Button Width="100" Content="..." Click="MenuItem_Click"/>
        <Button Width="100" Content="..."/>
        <Button Width="100" Content="..."/>
    </StackPanel>
</local:SizeAwareControl>

这只是一个起点 - 您可能需要一些更详细的逻辑来确定良好的宽度和高度值。第一个子节点上的MaxHeight可以滚动长文本(而不是生成一个非常高的窗口),第二个子节点上的MinWidth可以确保少量按钮的宽度。