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

Wpf 尽可能以声明方式实现XAML中的可调整大小、可隐藏的窗格,wpf,xaml,Wpf,Xaml,使用C#、XAML和WPF,我想创建一个从窗口底部边缘展开的窗格,类似于许多桌面电子邮件客户端中邮件内容的窗格。我想把它完全隐藏起来。通过在其内容和窗口主内容之间拖动拆分器,可以调整其大小 我设法以声明的方式实现了它,但它有一个bug,我无法在不牺牲声明性实现的清晰性的情况下修复它,其中代码隐藏主要关注支持的操作,而不是直接处理已使用的UI组件的状态 整个布局是一个三行网格,中间一行包含一个GridSplitter 名为PaneVisible的依赖属性双向绑定到窗格中GridSplitter和

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

我设法以声明的方式实现了它,但它有一个bug,我无法在不牺牲声明性实现的清晰性的情况下修复它,其中代码隐藏主要关注支持的操作,而不是直接处理已使用的UI组件的状态

  • 整个布局是一个三行网格,中间一行包含一个
    GridSplitter
  • 名为
    PaneVisible
    的依赖属性双向绑定到窗格中
    GridSplitter
    ContentControl
    的可见性
  • PaneVisible==false
    时,中间行会自动折叠,因为它的
    Height
    设置为
    Auto
    。通过
    DataTrigger
    将最下面一行的
    高度设置为
    0
当我只是来回切换
PaneVisible
时,它会按需要工作拖动
GridSplitter
后,最后一行不再折叠
,这是不需要的。我知道
RowDefinition.Height
获取一个本地值,并且不再使用(覆盖)style中指定的值(包括
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>

我认为,正如你已经知道的,你无论如何都需要重新设置高度。即使有办法,我想也不容易读


如果我是你,我会为这个目的定义
UserControl
,命名为“SplitPanel”。此拆分面板具有上部图元、下部图元和下部面板可见性的一些属性。此SplitPanel在代码隐藏上只有该逻辑。我希望它很容易实现,并且便于将来的维护,而且您可以使主XAML及其代码保持简单。

我认为,正如您已经知道的,您无论如何都需要重置高度。即使有办法,我想也不容易读

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

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;
    }
  }
}