XAML元素填充所有剩余空间

时间:2016-08-28 05:29:26

标签: c# wpf xaml

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

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

元素应该从上到下堆叠,因此Stack Panel看起来很自然。但是第三个元素必须占据前两个和底部没有的剩余空间。无论我尝试什么,它要么占用太多空间,要么占用太少空间。如果我给它一个具体的像素大小,如上所述,它似乎无法正常工作。

我尝试过的最新产品是Dock Panel。虽然它在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伸展并填充其他三个空间不占用的空间的想法吗?

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

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

感谢大家的投入!

2 个答案:

答案 0 :(得分:5)

有很多可能的方法。最简单的方法之一是将您的元素包含在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

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

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

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

答案 1 :(得分:2)

删除画布的垂直对齐