c# - XAML 元素填充所有剩余空间

标签 c# wpf xaml

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

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

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

我最近尝试的是停靠面板。虽然它在 Visual Studio 设计器中看起来正确,但在执行时,第三个元素( Canvas )会完全覆盖底部元素。

我的 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 拉伸(stretch)并填充其他三个不占用的所有空间有什么想法吗?

更新 由于@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;

所以我四处寻找,发现这里关于“Stack”的评论说要获取 WorkArea 而不是 PrimaryScreenHeight。我试过了,瞧!,出现了整个应用程序窗口。

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

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

感谢大家的投入!

最佳答案

对此有多种可能的方法。最直接的方法之一是将您的元素包含在 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>

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

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

four row grid with border and canvas filling the third row

(我将窗口背景设置为灰色,这样您的白色文本和边框就可以看到了。)

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

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

关于c# - XAML 元素填充所有剩余空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39188293/

相关文章:

C# 访问接口(interface)数组中对象的非接口(interface)方法

c# - 查找绑定(bind)到对象的 XAML 框架元素

c# - 在 proc 中使用外部 int 时 CSharp 程序崩溃

c# - 计算列表的每个元素出现在多少个连续的子列表中

wpf - MVVM 单元测试 - 消息总线只工作一次

c# - 如何使 DataTemplate 响应 WPF 中的双击?

c# - Xamarin 表单选择器级联

C# WPF 将本地化文本绑定(bind)到元素

c# - 当你有句柄时是 int 还是 IntPtr?

.net - 通过添加 View State 功能修改现有的 MVVM 基础架构