WPF中Popup控制元件的使用

Dwaynerbing發表於2022-06-19

一、Popup控制元件的主要屬性

Popup表示具有內容的彈出視窗,其主要屬性為:

  1. Child:獲取或設定 Popup控制元件的內容。
  2. IsOpen:獲取或設定一個值,該值指示Popup 是否可見
  3. Placement:獲取或設定 Popup 控制元件開啟時的控制元件方向,並指定Popup 控制元件在與螢幕邊界重疊時的控制元件行為
  4. PlacementTarget:獲取或設定當開啟 Popup 控制元件時該控制元件相對於其放置的元素。
  5. PopupAnimation:獲取或設定Popup 控制元件的開啟和關閉動畫。
  6. StaysOpen:獲取或設定一個值,該值指示當 Popup 控制元件焦點不再對準時,是否關閉該控制元件。

Popup主要事件為:

  1. Opened:當IsOpen 屬性更改為 true 時發生。

    private void PopupOpening(object sender, EventArgs e)
    {
        //Code to execute when Popup opens
    }
    
  2. Closed:當IsOpen 屬性更改為 false 時發生。

    private void PopupClosing(object sender, EventArgs e)
    {
        //Code to execute when Popup closes
    }
    

二、Popup控制元件使用

我們使用Popup實現一個功能:當文字框獲取到焦點時,彈出下拉框,裡面選擇水果種類,具體效果如下圖所示:

20220619_224733_ (1)

相關的介面程式碼為:

  <Window.Resources>
        <x:Array x:Key="MyArray" Type="system1:String">
            <system1:String>西瓜</system1:String>
            <system1:String>葡萄</system1:String>
            <system1:String>芒果</system1:String>
            <system1:String>獼猴桃</system1:String>
        </x:Array>
    </Window.Resources>
    <Grid Margin="20">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="100"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="0"  Height="30" BorderThickness="1" 
                 VerticalContentAlignment="Center"
                 Padding="10,0"
                 x:Name="TestTextBox"
                 ToolTip="{StaticResource MyArray}">
        </TextBox>
        <Button Grid.Column="1" Content="搜尋" Margin="10,0" Height="30" Click="ButtonBase_OnClick"></Button>
        <Popup Grid.Column="0"
               AllowsTransparency="True"
               PopupAnimation="Slide"
               PlacementTarget="{Binding ElementName=TestTextBox}"
               Placement="Bottom"
               Width="{Binding ElementName=TestTextBox, Path=ActualWidth}"
               IsOpen="{Binding ElementName=TestTextBox, Path=IsKeyboardFocused, Mode=OneWay}">
            <ListBox ItemsSource="{Binding ElementName=TestTextBox, Path=ToolTip}"
                     SelectedItem="{Binding ElementName=TestTextBox, Path=Text, Mode=OneWayToSource}"></ListBox>
        </Popup>
    </Grid>

為了,讓Popup控制元件能夠跟隨目標控制元件移動,需要增加一個工具類,具體如下所示:

 public class PopupHelper
    {
        /// <summary>
        /// 附加屬性:跟隨放置控制元件而移動
        /// </summary>
        public static readonly DependencyProperty PopupPlacementTargetProperty = DependencyProperty.RegisterAttached("PopupPlacementTarget", typeof(DependencyObject), typeof(PopupHelper), new PropertyMetadata(null, OnPopupPlacementTargetChanged));

        public static DependencyObject GetPopupPlacementTarget(DependencyObject obj)
        {
            return (DependencyObject)obj.GetValue(PopupPlacementTargetProperty);
        }
        public static void SetPopupPlacementTarget(DependencyObject obj, DependencyObject value)
        {
            obj.SetValue(PopupPlacementTargetProperty, value);
        }

        private static void OnPopupPlacementTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is System.Windows.Controls.Primitives.Popup pop && e.NewValue is DependencyObject placementTarget)
            {
                var window = Window.GetWindow(placementTarget);
                if (window != null)
                {
                    window.LocationChanged += delegate
                    {
                        var mi = typeof(System.Windows.Controls.Primitives.Popup).GetMethod("UpdatePosition", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                        mi?.Invoke(pop, null);
                    };
                }
            }
        }
    }

該附加屬性的使用如下所示:

 <Popup local:PopupHelper.PopupPlacementTarget="{Binding ElementName=TestTextBox}"></Popup>

相關文章