zoukankan      html  css  js  c++  java
  • (转WPF SDK)Popup my Control

    http://blogs.msdn.com/wpfsdk/archive/2007/04/27/popup-your-control.aspx

    Popup your control

    You want a custom control to behave like a Popup and appear over your application and other windows? So you should inherit from Popup, right? Not necessarily.

     

    Another approach is to create your custom control, add a Popup to it, and use the popup service. In fact, this is exactly what ContextMenu and ToolTip do. Popup, ContextMenu, and ToolTip all have the following properties defined, but the ContextMenu and ToolTip actually leave it up to the Popup to implement them.

     

    • Placement
    • PlacementTarget
    • PlacementRectangle
    • HorizontalOffset
    • VerticalOffset
    • IsOpen

     

    The ContextMenu and ToolTip call the Popup.CreateRootPopup which sets the Popup.Child property to the control and binds the six properties of the Popup to the control. 

     

    Doing the same for your custom control is easy enough. I created a control that accepts text and is editable. I could have added a TextBox to a control that inherits from Popup, but then I either hide the functionality of the TextBox from application developers, or have to expose TextBox through a property. Furthermore, Popup does not inherit from Control, so I wouldn’t have the ability to template the control. Instead, I inherited from TextBox. Below is the beginning of my control, EditablePopup.

     

        public partial class EditablePopup : System.Windows.Controls.TextBox

        {

            Popup _parentPopup;

     

            public EditablePopup()

                : base()

            {

            }

     

            static EditablePopup()

            {

                //This OverrideMetadata call tells the system that this element

                //wants to provide a style that is different than its base class.

                //This style is defined in themes"generic.xaml

                DefaultStyleKeyProperty.OverrideMetadata(typeof(EditablePopup),

                    new FrameworkPropertyMetadata(typeof(EditablePopup)));

            }

        }

     

     

    I don’t want my EditablePopup to look like a normal TextBox, so I define my Template to contain a border and a decorator.

     

     <Style TargetType="{x:Type local:EditablePopup}">

        <Setter Property="Margin" Value="1"/>

        <Setter Property="Template">

          <Setter.Value>

            <!--Create a TextBox that looks "flat".

                  The control template for a TextBox or RichTextBox must

                  include an element tagged as the content host. An element is

                  tagged as the content host element when it has the special name

                  PART_ContentHost. The content host element must be a ScrollViewer,

                  or an element that derives from Decorator. 

                  -->

            <ControlTemplate TargetType="{x:Type local:EditablePopup}">

              <Border Background="{TemplateBinding Background}"

                      BorderBrush="{TemplateBinding BorderBrush}"

                      BorderThickness="{TemplateBinding BorderThickness}">

                <Decorator x:Name="PART_ContentHost"/>

              </Border>

            </ControlTemplate>

          </Setter.Value>

        </Setter>

     </Style>

     

     

    Now I need to add the six properties I mentioned above to my control. Because Popup has these properties, creating the first five is pretty straightforward. You just need to call AddOwner on each DependencyProperty of the Popup and provide CLR Accessors. For more information about creating dependency properties, see Custom Dependency Properties in the SDK. Here are the declarations for Placement, PlacementTarget, PlacementRectangle, HorizontalOffset, and VerticalOffset:

     

            //Placement

            public static readonly DependencyProperty PlacementProperty =

                        Popup.PlacementProperty.AddOwner(typeof(EditablePopup));

     

            public PlacementMode Placement

            {

                get { return (PlacementMode)GetValue(PlacementProperty); }

                set { SetValue(PlacementProperty, value); }

            }

     

            //PlacementTarget

            public static readonly DependencyProperty PlacementTargetProperty =

               Popup.PlacementTargetProperty.AddOwner(typeof(EditablePopup));

     

            public UIElement PlacementTarget

            {

                get { return (UIElement)GetValue(PlacementTargetProperty); }

                set { SetValue(PlacementTargetProperty, value); }

            }

     

            //PlacementRectangle

            public static readonly DependencyProperty PlacementRectangleProperty =

                        Popup.PlacementRectangleProperty.AddOwner(typeof(EditablePopup));

     

            public Rect PlacementRectangle

            {

                get { return (Rect)GetValue(PlacementRectangleProperty); }

                set { SetValue(PlacementRectangleProperty, value); }

            }

     

            //HorizontalOffset

            public static readonly DependencyProperty HorizontalOffsetProperty =

                Popup.HorizontalOffsetProperty.AddOwner(typeof(EditablePopup));

     

            public double HorizontalOffset

            {

                get { return (double)GetValue(HorizontalOffsetProperty); }

                set { SetValue(HorizontalOffsetProperty, value); }

            }

     

            //VerticalOffset

            public static readonly DependencyProperty VerticalOffsetProperty =

                    Popup.VerticalOffsetProperty.AddOwner(typeof(EditablePopup));

     

            public double VerticalOffset

            {

                get { return (double)GetValue(VerticalOffsetProperty); }

                set { SetValue(VerticalOffsetProperty, value); }

            }

     

    Adding the IsOpen property is a little more involved, but isn’t that complex. When you define the DependenceProperty for IsOpen, you also need to provide a callback function when the value for IsOpen changes. When IsOpen is true, create the Popup and call Popup.CreateRootPopup.

     

            public static readonly DependencyProperty IsOpenProperty =

                    Popup.IsOpenProperty.AddOwner(

                            typeof(EditablePopup),

                            new FrameworkPropertyMetadata(

                                    false,

                                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,

                                    new PropertyChangedCallback(OnIsOpenChanged)));

     

            public bool IsOpen

            {

                get { return (bool)GetValue(IsOpenProperty); }

                set { SetValue(IsOpenProperty, value); }

            }

     

            private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

            {

                EditablePopup ctrl = (EditablePopup)d;

     

                if ((bool)e.NewValue)

                {

                    if (ctrl._parentPopup == null)

                    {

                        ctrl.HookupParentPopup();

                    }

                }

            }

     

            private void HookupParentPopup()

            {

     

                _parentPopup = new Popup();

     

                _parentPopup.AllowsTransparency = true;

     

                Popup.CreateRootPopup(_parentPopup, this);

            }

     

    Now that we’ve made the control, there are a few things to keep in mind before you use the control. First, set PlacementTarget before you call CreateRootPopup. If you call CreateRootPopup first, the PlacementTarget is ignored. Essentially this means you need to set PlacementTarget before setting IsOpen to true, just like you need to for a Popup.

     

    Second, CreateRootPopup sets the Child property of the Popup to your custom control. As a result, your custom control cannot have a logical or visual parent and the following doesn’t work:

     

        <WrapPanel>

          <src:EditablePopup IsOpen="True">Hello</src:EditablePopup>

        </WrapPanel>

     

    Instead, you need to create your control as a resource, or create it in code. In my project, I created the EditablePopup controls in code.

     

                budapestDesc = new EditablePopup();

                budapestDesc.Text = "Title:"tBudapest, Hungary"n" +

                                    "Description:"n"tHungarian Parliament Building and the Danube River";

                budapestDesc.PlacementTarget = budapestPic;

     

    Now I can position the EditablePopup, just like I would a Popup, ContextMenu, or ToolTip, by setting the Placement, PlacementRectangle, HorizontalOffset, and VerticalOffset properties.

     

    I’ve attached the EditablePopup zip file so you can download and experiment with it.

    Published Friday, April 27, 2007 2:58 PM by wcsdkteam
    Attachment(s): EditablePopup.zip
  • 相关阅读:
    ajax GET 传输中文乱码
    php 验证码 图像存在错误 无法显示 解决方法
    ajax 简单实例
    PHP continue break 区别 用法
    php注意事项
    php7注意事项
    腾讯2015后台模拟题
    【leetcode】_3Sum
    最小的k个数 2.5
    《Hadoop权威指南》笔记 第三章 并行复制及存档
  • 原文地址:https://www.cnblogs.com/liangouyang/p/1324231.html
Copyright © 2011-2022 走看看