WPF 弹出窗口:如何为弹出窗口制作可重复使用的模板?

Posted

技术标签:

【中文标题】WPF 弹出窗口:如何为弹出窗口制作可重复使用的模板?【英文标题】:WPF popup: how to make a reusable template for popups? 【发布时间】:2011-04-09 22:52:38 【问题描述】:

由于 Popup 不是从 Control 派生并且没有模板,我如何定义模板以使所有弹出窗口看起来都一样?我需要设计一个具有特定外观的并且不想每次使用时都复制标记。

这看起来很简单,但我不知道该怎么做。 Child 属性定义了一个逻辑树,但我不知道如何将其拉出到模板中并重用它。

【问题讨论】:

【参考方案1】:

取决于您希望弹出窗口的行为方式。如果它们只是为了以统一的方式显示信息,那么您可能希望拥有一个派生自 Window 的类,该类具有围绕 ContentPresenter 的标准格式和样式,然后将演示者的内容绑定到属性可以代表每个弹窗的自定义信息。

然后它只是在显示弹出窗口之前以编程方式插入您想要的任何自定义内容。

希望对您有所帮助。

【讨论】:

【参考方案2】:

我想做同样的事情,这就是我想出的:

我继承自 ContentPresenter,按照我的意愿设置了该控件的样式,然后将派生的 ContentPresenter 放在了我的 Popup 中,为了简单起见,我只使用了 2 个文本块,但很容易理解任何内容如何添加。

我的自定义控件:

using System.Windows;
using System.Windows.Controls;

namespace CustomControls

    [TemplatePart(Name = PART_PopupHeader, Type = typeof(TextBlock))]
    [TemplatePart(Name = PART_PopupContent, Type = typeof(TextBlock))]

    public class CustomPopupControl : ContentControl
    
        private const string PART_PopupHeader = "PART_PopupHeader";
        private const string PART_PopupContent = "PART_PopupContent";

        private TextBlock _headerBlock = null;
        private TextBlock _contentBlock = null;

        static CustomPopupControl()
        
            DefaultStyleKeyProperty.OverrideMetadata
                (typeof(CustomPopupControl), 
                new FrameworkPropertyMetadata(typeof(CustomPopupControl)));
        

        public override void OnApplyTemplate()
        
            base.OnApplyTemplate();
            _headerBlock = GetTemplateChild(PART_PopupHeader) as TextBlock;
            _contentBlock = GetTemplateChild(PART_PopupContent) as TextBlock;
        

        public static readonly DependencyProperty HeaderTextProperty =
            DependencyProperty.Register("HeaderText", typeof(string), typeof(CustomPopupControl), new UIPropertyMetadata(string.Empty));

        public string HeaderText
        
            get
            
                return (string)GetValue(HeaderTextProperty);
            
            set
            
                SetValue(HeaderTextProperty, value);
            
        

        public static readonly DependencyProperty ContentTextProperty =
            DependencyProperty.Register("ContentText", typeof(string), typeof(CustomPopupControl), new UIPropertyMetadata(string.Empty));

        public string ContentText
        
            get
            
                return (string)GetValue(ContentTextProperty);
            
            set
            
                SetValue(ContentTextProperty, value);
            
        
    

控件的样式:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                  
                xmlns:local="clr-namespace:CustomControls">

<Style TargetType="x:Type local:CustomPopupControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="x:Type local:CustomPopupControl">
                <Border CornerRadius="3" BorderThickness="1" BorderBrush="White">
                    <Border.Background>
                        <SolidColorBrush Color="#4b4b4b" Opacity="0.75"/>
                    </Border.Background>
                    <Border.Effect>
                        <DropShadowEffect ShadowDepth="0"
                            Color="White"
                            Opacity="1"
                            BlurRadius="5"/>
                    </Border.Effect>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <TextBlock Text="TemplateBinding HeaderText"
                                   Grid.Row="0"
                                   Foreground="#5095d6"
                                   FontWeight="Bold"
                                   VerticalAlignment="Bottom"
                                   Margin="TemplateBinding Margin"
                                   HorizontalAlignment="Left"/>
                        <Rectangle Grid.Row="1" Stroke="AntiqueWhite" Margin="1 0"></Rectangle>
                        <TextBlock Grid.Row="2"
                                   Grid.ColumnSpan="2"                                
                                   x:Name="PART_TooltipContents"
                                   Margin="5, 2"
                                   Text="TemplateBinding ContentText"
                                   TextWrapping="Wrap"
                                   MaxWidth="200"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

控件的使用:

<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
    <Button x:Name="Button1" Content="Button with popup" HorizontalAlignment="Center">
    </Button>
    <Button x:Name="Button2" Content="Another button with popup" HorizontalAlignment="Center">
    </Button>
    <Popup  IsOpen="True"
        FlowDirection="LeftToRight"
        Margin="10"
        PlacementTarget="Binding ElementName=Button1" 
        Placement="top" 
        StaysOpen="True">
        <local2:CustomPopupControl HeaderText="Some Header Text" ContentText="Content Text that could be any text needed from a binding or other source" Margin="2">

        </local2:CustomPopupControl>
    </Popup>
    <Popup  IsOpen="True"
        FlowDirection="LeftToRight"
        Margin="10"
        PlacementTarget="Binding ElementName=Button2" 
        Placement="Bottom" 
        StaysOpen="True">
        <local2:CustomPopupControl HeaderText="Different header text" ContentText="Some other text" Margin="2">

        </local2:CustomPopupControl>
    </Popup>
</StackPanel>

我尝试说明一些属性如何在所有控件中保持不变,其他属性可以为每个控件自定义,其他属性可以绑定到 TemplatePart,这是最终结果:

【讨论】:

以上是关于WPF 弹出窗口:如何为弹出窗口制作可重复使用的模板?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用拇指使 WPF 弹出窗口可拖动?

WPF 动画窗口可见性更改

php如何制作弹出窗口

wpf 窗口弹出问题

wpf弹出的窗口只能是一个?

wpf 如何让弹出窗口总在屏幕范围之内?