开发者

WPF popup: how to make a reusable template for popups?

Since Popup doesn't derive from Control and doesn't have a template, how can I define a template so that all popups look the same? I need to design one that has a certain loo开发者_运维技巧k and don't want to have to copy markup each time one is used.

This seems pretty easy but I can't figure out how to do it. The Child property defines a logical tree but I don't see how you can pull that out into a template and reuse it.


I was looking to do the same thing and here is what I came up with:

I inherited from ContentPresenter, styled that control as I wanted and than placed the derived ContentPresenter inside my Popup, I only used 2 text blocks for the simplicity but it is easy to understand how any content could be added.

My custom control:

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

Style for the control:

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

The use of the control:

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

I tried illustrating how some properties can be constant across all controls, others can be customized per control and others could be bound to TemplatePart, here is the final result:

WPF popup: how to make a reusable template for popups?


Depends how you want your pop-ups to behave. If they're just for displaying information in a uniform manner, than you might want to have a class that derives from Window that has the standard formats and styling wrapped around a ContentPresenter then bind the content of the presenter to a property which can represent the custom information for each pop-up.

Then its just a matter of programatically inserting whatever custom content you want before displaying the pop-up window.

Hope it helps.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜