XAML中可调整大小,可隐藏的窗格尽可能以声明方式实现

时间:2016-11-01 16:20:14

标签: wpf xaml

使用C#,XAML和WPF,我想创建一个从窗口底部边缘展开的窗格,类似于许多桌面电子邮件客户端中的邮件内容的窗格。我希望能够完全隐藏它。它应该通过在其内容和窗口的主要内容之间拖动拆分器来调整大小。

我设法以声明方式实现它,但它有一个我无法修复的错误,而不会牺牲声明性实现的清晰度,其中代码隐藏重点关注支持的操作,并且不会直接摆弄使用过的UI组件的状态。

  • 整个布局是一个三行网格,中间一行包含GridSplitter
  • 名为PaneVisible的依赖项属性与窗格中GridSplitterContentControl的可见性双向绑定。
  • PaneVisible == false时,中间行会自动折叠,因为Height设置为Auto。底行的Height通过0设置为DataTrigger

当我只是来回切换PaneVisible时,它会按预期工作。 拖动GridSplitter后,最后一行永远不会崩溃,这是不受欢迎的。我知道RowDefinition.Height获取了一个本地值,并且不再使用(重写)样式中指定的值(包括DataTrigger)。

我考虑引入另一个依赖项属性PaneHeight,但是我未能设置绑定,因此当PaneVisible == false时,RowDefinition.Height为0而PaneHeight会保留原始值。是否必须将其价值设定为唯一的选择,还是有一种解决我问题的声明方式?

也欢迎有关整体设计的建议。我几乎没有使用UI编程的经验。

标记:

<Window x:Class="WpfTestingApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfTestingApplication"
        Title="MainWindow" Height="350" Width="525">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition MinHeight="20" Height="*" />
      <RowDefinition Height="Auto" />
      <RowDefinition>
        <RowDefinition.Style>
          <Style TargetType="RowDefinition">
            <Setter Property="Height" Value="100" />
            <Style.Triggers>
              <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=local:MainWindow}, Path=PaneVisible}" Value="false">
                <Setter Property="Height" Value="0" />
              </DataTrigger>
            </Style.Triggers>
          </Style>
        </RowDefinition.Style>
      </RowDefinition>
    </Grid.RowDefinitions>
    <ToggleButton Grid.Column="0" Click="TogglePane_Click">Toggle pane</ToggleButton>
    <GridSplitter Grid.Row="1" Height="9" HorizontalAlignment="Stretch" Visibility="{Binding RelativeSource={RelativeSource AncestorType=local:MainWindow}, Path=PaneVisible, Converter={StaticResource BoolToVis}}" />
    <ContentControl Grid.Row="2" Name="Pane" Visibility="{Binding RelativeSource={RelativeSource AncestorType=local:MainWindow}, Path=PaneVisible, Converter={StaticResource BoolToVis}}">
      <TextBlock>Yadayada</TextBlock>
    </ContentControl>
  </Grid>
</Window>

Application.Resources中,我添加了<BooleanToVisibilityConverter x:Key="BoolToVis" />

代码隐藏:

using System;
using System.Windows;

namespace WpfTestingApplication
{
  public partial class MainWindow : Window
  {
    public static readonly DependencyProperty PaneVisibleProperty =
      DependencyProperty.Register("PaneVisible", typeof(bool), typeof(MainWindow), new PropertyMetadata(false));

    public bool PaneVisible
    {
      get { return (bool)GetValue(PaneVisibleProperty); }
      set { SetValue(PaneVisibleProperty, value); }
    }

    public MainWindow()
    {
      InitializeComponent();
    }

    private void TogglePane_Click(object sender, RoutedEventArgs e)
    {
      PaneVisible = !PaneVisible;
    }
  }
}

1 个答案:

答案 0 :(得分:0)

我认为,正如您所知,无论如何,您需要以某种方式重置高度。即使有办法,我想这也不容易阅读。

如果我是你,我会为此目的定义UserControl,名为“SplitPanel”。此SplitPanel具有上部元素,下部元素和下部面板可见性的一些属性。这个SplitPanel只有代码背后的逻辑。我希望它易于实现和将来的维护,并且您可以将主要的XAML及其代码保持简单。