65.9K
CodeProject 正在变化。 阅读更多。
Home

如何下拉任何窗口?

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (37投票s)

2012 年 7 月 10 日

CPOL

3分钟阅读

viewsIcon

79666

downloadIcon

2534

向您展示如何使用 Popup 创建您自己的类似下拉窗口。

 
 
 

引言

下拉窗口作为对话框的轻量级替代方案,被广泛应用于各种软件应用中。Popup 类是一个 UI 容器,可以容纳任何 UI 元素,并且可以在另一个 UI 容器中弹出。本文向您展示如何使用 Popup 类创建您自己的下拉窗口。

背景

从功能上讲,Popup 是模态或非模态对话框的轻量级替代方案。可能最广为人知的 Popup 示例是 ComboBox,也称为下拉列表。如果您使用 Expression Blend 来检查 ComboBox,您会发现它由一个 ToggleButton 和一个承载 ItemsPresenterPopup 组成。您当然可以将 ItemsPresenter 替换为其他内容,以便您可以自定义 ComboBox。 并且您可以创建自己的类似下拉的 Popup 来承载任何 UI 元素。

Using the Code

本文向您展示:

  • 如何切换 Popup 的打开/关闭;
  • 如何定位容器窗口;
  • 如何承载用户控件;
  • 如何绑定数据。

包含的示例演示了不同的方法。 通常,屏幕的左侧显示轻量级方法; 而屏幕的右侧显示适用于复杂情况的方法。 在下面,我们将使用 ToggleButtonPopup 类来构建下拉列表; 请注意它们之间的集成。

打开/关闭切换

Popup 的打开或关闭由 Popup.IsOpen 属性处理。 因此,您需要将其绑定到代码中的布尔属性。 控制打开/关闭的最简单方法是使用 ToggleButton。 因此,Popup.IsOpenToggleButton.IsChecked 的属性值应同步。 对于简单的情况,您可以使用元素绑定,如下所示:

<ToggleButton x:Name="dgDropdown" Content="q" FontFamily="Wingdings 3"  />

<Popup IsOpen="{Binding IsChecked, Mode=TwoWay, ElementName=dgDropdown}" StaysOpen="False"
       PlacementTarget="{Binding ElementName=dgDropdown}" Placement="Bottom" >

如果您需要更多控制,您可以将两个属性绑定到 ViewModel 中声明的布尔属性,该 ViewModel 实现 INotifyPropertyChanged 接口以刷新属性更改。

<ToggleButton x:Name="icDropdown" Content="q" FontFamily="Wingdings 3"
              IsChecked="{Binding IsItemsControlOpen, Mode=TwoWay}" />  

<Popup IsOpen="{Binding IsItemsControlOpen, Mode=TwoWay}" StaysOpen="False"
       PlacementTarget="{Binding ElementName=icDropdown}" Placement="Bottom" PopupAnimation="Slide">
职位

为了实现下拉外观,您需要指定 PopupToggleButton 的相对位置。 您可以将 Popup.PlacementTarget 属性绑定到 ToggleButton 的元素名称。 Popup.Placement 属性指定 Popup 打开时的方向和行为。 由于您需要在 ToggleButton 下方打开 Popup,因此您需要将此属性设置为 Bottom

作为第二种方式,您也可以将 Popup 视为 ToggleButton 内容的一部分,并将 Popup 嵌套在 ToggleButton 中。 这样,Popup.PlacementTarget 会自动与 ToggleButton 关联。 请注意,由于我设置了 ToggleButton.Padding,因此我需要调整 Popup.HorizontalOffsetPopup.VerticalOffset 以使两个控件正确对齐。 偏移值应包括 ToggleButton 的边框厚度。

<ToggleButton IsChecked="{Binding IsItemsControlOpen, Mode=TwoWay}" 
              HorizontalAlignment="Left" Padding="4, 2" Margin="10">
    <ToggleButton.Content>
        <StackPanel>
        <TextBlock>                      
            <Run Text="Selection" />                       
            <Run Text="q" FontFamily="Wingdings 3" />
        </TextBlock>
            <Popup IsOpen="{Binding IsItemsControlOpen, Mode=TwoWay}" StaysOpen="False"
                   Placement="Bottom" PopupAnimation="Slide"
                   HorizontalOffset="-5" VerticalOffset="3">
                <Border BorderBrush="SlateBlue" BorderThickness="1"  CornerRadius="2" >
                    <local:MyUserControl />
                </Border>
            </Popup>
        </StackPanel>
    </ToggleButton.Content>
</ToggleButton> 

轻量级承载方式

Popup 可以承载许多不同的 UI 元素。 如果您的情况很简单,只需要承载几个控件,您可以在 XAML 中执行此操作,如示例屏幕的左侧所示。 这是 XAML 代码:

<Popup IsOpen="{Binding IsChecked, Mode=TwoWay, ElementName=dgDropdown}" StaysOpen="False"
        PlacementTarget="{Binding ElementName=dgDropdown}" Placement="Bottom" PopupAnimation="Slide">
    <Border BorderBrush="SlateBlue" BorderThickness="1"  CornerRadius="2" >
        <Grid Background="LightGray">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <DataGrid ItemsSource="{Binding Data}" CanUserAddRows="False" IsReadOnly="True"
                        RowHeaderWidth="0" HorizontalGridLinesBrush="Transparent" 
                        VerticalGridLinesBrush="Transparent" Margin="2">
                <i:Interaction.Behaviors>
                    <local:ColumnHeaderBehavior />
                </i:Interaction.Behaviors>
            </DataGrid>
            <TextBox Grid.Row="1" 
                     Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                     Height="100" Margin="2"/>
        </Grid>
    </Border>
</Popup> 

请参阅 A Smart Behavior for DataGrid.AutoGenerateColumns 了解如何使用 Behavior 和 Attribute 进行列标题显示。

承载用户控件

如果您需要在 Popup 中承载很多东西,并且可能具有复杂的逻辑,您可以将所有内容包装在 UserControl 中,并将其承载在 Popup 中,如示例屏幕的右侧所示。

<Popup IsOpen="{Binding IsItemsControlOpen, Mode=TwoWay}" StaysOpen="False"
       PlacementTarget="{Binding ElementName=icDropdown}" Placement="Bottom" PopupAnimation="Slide">
    <Border BorderBrush="SlateBlue" BorderThickness="1" CornerRadius="2" >
        <local:MyUserControl />
    </Border>
</Popup>

关注点

通过将 Popup 的打开/关闭与 ToggleButton 同步,您可以有效地创建自己的 Popup 窗口。 对齐两个控件的相对位置将使外观像下拉列表。 您可以进一步自定义 PopupBorder 以增强用户体验。

© . All rights reserved.