【问题标题】:XAML element fill all remaining spaceXAML 元素填充所有剩余空间
【发布时间】:2016-08-29 07:09:07
【问题描述】:

我有一个 WPF 应用程序,我正在尝试正确定位元素。只有四个元素,所以它应该很简单,但我就是无法让它发挥作用。

一个问题是窗口会在出现时将自身调整为(大约)桌面窗口的大小,因此它没有固定大小。

元素应该从上到下堆叠,所以 Stack Panel 看起来很自然。但是第三个元素必须占用顶部两个和底部不占用的所有剩余空间。无论我尝试什么,它要么占用太多空间,要么太少。如果我给它一个具体的像素大小,我似乎只能让它工作,如上所述,这是行不通的。

我尝试过的最新产品是 Dock Panel。虽然它在 Visual Studio 设计器中看起来是正确的,但在执行时,第三个元素(画布)完全覆盖了底部元素。

我的 XAML:

<DockPanel>
    <Button x:Name="btnClose" DockPanel.Dock="Top" Content="X" 
            HorizontalAlignment="Right" Margin="0,5,5,0" VerticalAlignment="Top" 
            Width="Auto" Height="Auto" Background="Black" 
            Foreground="White" Click="btnClose_Click"/>
    <Label x:Name="lblTitle" DockPanel.Dock="Top" Content="My Title" 
           HorizontalAlignment="Center" VerticalAlignment="Top" Width="Auto" 
           Foreground="White" FontWeight="Bold" FontSize="22"/>

    <Label x:Name="lblControls" DockPanel.Dock="Bottom" Content="Placeholder" 
           HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="Auto" 
           Height="Auto" Foreground="White" FontWeight="Bold" FontSize="22"/>

    <Border x:Name="CanvasBorder" BorderBrush="White" BorderThickness="5" >
        <Canvas x:Name="cvsChart" Grid.Row="0" HorizontalAlignment="Stretch"
                VerticalAlignment="Top" Width="Auto">
        </Canvas>
    </Border>
</DockPanel>

知道如何让 Canvas 拉伸并填充其他三个不占用的所有空间吗?

更新 由于@Peter Duniho 几乎向我证明了代码有效,因此我尝试了一个实验并删除了我在窗口出现时调整大小的代码。把它拿出来,窗口完全正确地出现了。这就是我将其调整为(主要)桌面大小的方法:

public const int WINDOW_OFFSET = 10;
...

int screenWidth = (int)System.Windows.SystemParameters.PrimaryScreenWidth;
int screenHeight = (int)System.Windows.SystemParameters.PrimaryScreenHeight;

// center this window in desktop
Width = screenWidth - WINDOW_OFFSET;
Height = screenHeight - WINDOW_OFFSET;
Left = WINDOW_OFFSET/2;
Top = WINDOW_OFFSET/2;

所以我四处摸索,并在“堆栈”上找到了一条评论,该评论说要获取 WorkArea 而不是 PrimaryScreenHeight。我试过了,瞧!,整个应用程序窗口出现了。

int screenWidth = (int)System.Windows.SystemParameters.WorkArea.Width;
int screenHeight = (int)System.Windows.SystemParameters.WorkArea.Height;

事实证明,底行正在显示,我只是看不到它,因为它出现在屏幕底部下方。现在我可以看到了,我又回到了开发天堂!

感谢大家的意见!

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    对此有多种可能的方法。最直接的方法之一是将您的元素包含在Grid 中,并将除第三行高度之外的所有元素设置为Auto

      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
          <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Button x:Name="btnClose" Content="X" Grid.Row="0"
                HorizontalAlignment="Right" Margin="0,5,5,0" VerticalAlignment="Top" 
                Width="Auto" Height="Auto" Background="Black" 
                Foreground="White" Click="btnClose_Click"/>
        <Label x:Name="lblTitle" Content="My Title" Grid.Row="1"
               HorizontalAlignment="Center" VerticalAlignment="Top" Width="Auto" 
               Foreground="White" FontWeight="Bold" FontSize="22"/>
    
        <Label x:Name="lblControls" Content="Placeholder" Grid.Row="3"
               HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="Auto" 
               Height="Auto" Foreground="White" FontWeight="Bold" FontSize="22"/>
    
        <Border x:Name="CanvasBorder" BorderBrush="White" BorderThickness="5" Grid.Row="2">
          <Canvas x:Name="cvsChart" Grid.Row="0" HorizontalAlignment="Stretch"
                    VerticalAlignment="Top" Width="Auto">
          </Canvas>
        </Border>
      </Grid>
    

    网格的行定义高度的默认设置是"*",表示将所有剩余空间分配给具有该设置的所有行。只有一行使用该设置,它会获得所有剩余空间。

    这会产生一个如下所示的窗口:

    (我将窗口背景设置为Gray,以便您的白色文本和边框可见。)

    另一个选项实际上是使用DockPanel。在我看来,您尝试的主要问题是您将lblControls 元素设置为DockPanel.Dock="Bottom",而它应该是Top。当我将其更改为 Top 时,它似乎对我来说工作正常。

    根据您在下面的评论,您似乎确实希望将lblControls 设置为DockPanel.Dock="Bottom",实际上您发布的代码似乎也可以满足您的需求。我不清楚与您发布的代码有何不同以及您希望它做什么。如果您能提供一个可靠地重现问题的良好 Minimal, Complete, and Verifiable code example 会更好。

    【讨论】:

    • 感谢您的回复,但两种方法都不起作用。边框和画布应该出现在窗口的中间。据我了解,最后添加它而不给它一个停靠位置应该可以做到这一点。当我将lblControls 设置为Top 时,它们出现在顶部,在Border 和Canvas 上方,正如他们被告知的那样,而不是他们应该的那样。网格方法也不起作用。我给所有行的高度为Auto,除了边框和画布,我给了"*"。它也隐藏了底部标签。
    • @Frecklefoot:“边框和画布应该出现在窗口中间”——抱歉,您的问题并不清楚预期的结果。您发布的代码确实执行此操作,将lblControls 放置在您指定的底部,将CanvasBordercvsChart 放在lblTitlelblControls 之间.我可以编辑Grid 示例以匹配您的评论,但最终不清楚为什么您的问题中的代码不能满足您的要求。根据您在此处的评论,在我看来确实如此。
    • 抱歉,我最初的问题不清楚。我担心这可能是个问题,因为我最后放置了 Border 和 Canvas。那我一定是做错了什么,因为我仍然得到底部标签被边框和画布完全覆盖。至少我认为这是正在发生的事情,因为当我运行它时我根本看不到它。但我的应用程序除了出现之外什么都没做。
    • 我刚才拿出了调整大小的窗口出现了,它确实有效。所以窗口的大小调整一定会以某种方式搞砸。所以这就是我的问题所在。感谢所有的帮助。我将您的输入标记为答案,因为它促使我​​真正找出问题所在......
    • @Freckle:好的,很高兴这至少有一点帮助。请记住,画布的内容不会被裁剪到画布上。也就是说,画布可以根据网格或停靠面板进行布局,但如果画布内的某些内容大于该布局,它将覆盖画布下方的所有布局。如果您需要有关调整大小行为的帮助,请发布一个新问题,并附上良好的 minimal reproducible example 以可靠地重现问题,并准确解释代码的作用以及您希望它做什么。考虑使用屏幕截图来具体显示这些细节。
    【解决方案2】:

    移除画布的垂直对齐方式

    【讨论】:

    • 谢谢,但这并没有什么不同。
    猜你喜欢
    • 1970-01-01
    • 2017-12-18
    • 2021-10-29
    • 1970-01-01
    • 2019-08-26
    • 2015-04-14
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多