WPF模板:AdornedElement没有显示!

时间:2010-04-20 12:56:42

标签: wpf silverlight templates controltemplate adorner

我想通过使用带有额外元素的模板和插入在正确位置的原始TextBox来向TextBox添加一些元素。我正在尝试使用AdornedElementPlaceholder,就像在进行Validation.ErrorTemplate时一样,但是AdornedElement没有显示出来。我尽可能地简化了这个例子:

<TextBox Text="Border me with my Template">
     <TextBox.Template>
      <ControlTemplate TargetType="{x:Type TextBox}">
       <Border BorderBrush="Green" BorderThickness="1">
        <AdornedElementPlaceholder/>
       </Border>
      </ControlTemplate>
     </TextBox.Template>
    </TextBox>  

结果只是一个绿色框,应该是我的文本框空间!

2 个答案:

答案 0 :(得分:1)

不幸的是,这不是它的工作原理。然而,它并不比那更困难。如果你想通过更改控件模板在文本框周围添加绿色边框,它会看起来更像这样:

<ControlTemplate TargetType="TextBox">
    <Border x:Name="Border"
            CornerRadius="2"
            Background="{TemplateBinding Background}"
            BorderBrush="Green"
            BorderThickness="1"
            SnapsToDevicePixels="True">
        <ScrollViewer x:Name="PART_ContentHost"/>
    </Border>
</ControlTemplate>

其中重要的部分是名为 PART_ContentHost 的ScrollViewer。 TextBox在应用模板时会查找该文件并使用它来托管文本,插入符号等。我认为您缺少的是当您覆盖元素的模板时,您将覆盖整个控制模板。不幸的是,你不能只改变点点滴滴,但事实就是如此。

当然,如果你想保持TextBox的原始外观,例如它仍然看起来像Win7 TextBox,你需要在ControlTemplate中做更多的事情。

对于它的价值,如果您正在谈论使用 Adorner ,看起来您尝试应用的模板会起作用。它与验证模板在WPF中的工作方式类似,但这是一个完整的故事。

哦,更简单的方法是将边框更改为绿色,您应该能够在TextBox本身上设置BorderBrush属性。当然,我真的不知道你到底想要什么。

- HTH 多尘

答案 1 :(得分:0)

我最终根据HeaderedContent Control进行了自定义控制。

它允许用户点击或覆盖某些内容,然后显示包含其他内容或相同内容的气泡。

用法:

<JsCustomControls:BaloonBox LabelText="{Binding Note}" WaterMark="Click to write Note" Type="ClickToShow">
<JsCustomControls:BaloonBox.Content>
<TextBox AcceptsReturn="True" Text="{Binding Path=Note}" TextWrapping="Wrap"></TextBox>
</JsCustomControls:BaloonBox.Content>
</JsCustomControls:BaloonBox>

用户控件的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;

namespace JsCustomControls
{
    public enum BaloonBoxTypeEnum
    {
        ClickToShow,
        MouseOverToShow,
        Manual
    }

    [TemplatePart(Name = BaloonBox.HeaderElement, Type = typeof(ContentPresenter))]
    [TemplatePart(Name = BaloonBox.ContentElement, Type = typeof(ContentPresenter))]
    [TemplatePart(Name = BaloonBox.PopUpElement, Type = typeof(Popup))]
    [TemplatePart(Name=BaloonBox.LabelElement,Type=typeof(Label))]
    public class BaloonBox : HeaderedContentControl
    {
        DispatcherTimer PopupTimer = new DispatcherTimer();

        private const string HeaderElement = "PART_HeaderContentControl";
        private const string ContentElement = "PART_ContenContentControl";
        private const string PopUpElement = "PART_PopUp";
        private const string LabelElement = "PART_HeaderLabel";

        private ContentPresenter headerContentControl;
        private ContentPresenter contentContentControl;
        private Popup popUp;
        private Label headerLabel;

        static BaloonBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(BaloonBox), new FrameworkPropertyMetadata(typeof(BaloonBox))); 
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            headerContentControl = GetTemplateChild(HeaderElement) as ContentPresenter;
            contentContentControl = GetTemplateChild(ContentElement) as ContentPresenter;
            popUp = GetTemplateChild(PopUpElement) as Popup;
            headerLabel = GetTemplateChild(LabelElement) as Label;
            if (headerContentControl != null) headerContentControl.MouseDown += new MouseButtonEventHandler(headerContentControl_MouseDown);
            if(headerLabel!=null)headerLabel.MouseDown+=new MouseButtonEventHandler(headerContentControl_MouseDown);
            if (headerContentControl != null) headerContentControl.MouseMove += new MouseEventHandler(headerContentControl_MouseMove);
            if(headerLabel!=null)headerLabel.MouseMove+=new MouseEventHandler(headerContentControl_MouseMove);
            PopupTimer = new DispatcherTimer();
            PopupTimer.Tick += new EventHandler(PopupTimer_Tick);
            if(string.IsNullOrEmpty(LabelText))
            {
                if (headerLabel != null) headerLabel.Foreground = Brushes.Gray;
                if (headerLabel != null) headerLabel.Content = WaterMark;
            }
            else
            {
                if (headerLabel != null) headerLabel.Foreground = Brushes.Black;
                if (headerLabel != null) headerLabel.Content = LabelText;
            }
        }

        void headerContentControl_MouseMove(object sender, MouseEventArgs e)
        {
            if (Type == BaloonBoxTypeEnum.MouseOverToShow)
            {
                if (popUp != null) popUp.IsOpen = true;
                PopupTimer.Interval = new TimeSpan(0, 0, 0, 2);
                PopupTimer.Start();
            }
        }
        void headerContentControl_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (Type == BaloonBoxTypeEnum.ClickToShow)
            {
                if (popUp != null) popUp.IsOpen = true;
                PopupTimer.Interval = new TimeSpan(0, 0, 0, 3);
                PopupTimer.Start();
            }

        }
        void PopupTimer_Tick(object sender, EventArgs e)
        {
            if (!headerContentControl.IsMouseOver && !contentContentControl.IsMouseOver && !contentContentControl.IsKeyboardFocusWithin)
            {
                PopupTimer.Stop();
                popUp.IsOpen = false;
            }
        }

        public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register("IsOpen",
                                                                                               typeof (bool),
                                                                                               typeof (BaloonBox),
                                                                                               new FrameworkPropertyMetadata
                                                                                                   (new PropertyChangedCallback
                                                                                                        (OnIsOpenChanged)));
        public bool IsOpen
        {
            get { return (bool) GetValue(IsOpenProperty); }
            set{SetValue(IsOpenProperty,value);}
        }

        private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            BaloonBox baloonBox = (BaloonBox)d;
            baloonBox.popUp.IsOpen =(bool)e.NewValue;          
        }

        public static readonly DependencyProperty WaterMarkProperty = DependencyProperty.Register("WaterMark",
                                                                                                  typeof (string),
                                                                                                  typeof (BaloonBox),
                                                                                                  new FrameworkPropertyMetadata
                                                                                                      (new PropertyChangedCallback
                                                                                                           (OnWatermarkChanged)));


        public string WaterMark
        {
            get { return (string)GetValue(WaterMarkProperty); }
            set { SetValue(WaterMarkProperty,value); }
        }

        private static void OnWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        public static readonly DependencyProperty LabelTextProperty = DependencyProperty.Register("LabelText",
                                                                                                  typeof (string),
                                                                                                  typeof (BaloonBox)
                                                                                                  ,new FrameworkPropertyMetadata(new PropertyChangedCallback(OnLabelTextChanged)));

        public string LabelText
        {
            get { return (string) GetValue(LabelTextProperty); }
            set
            {
                SetValue(LabelTextProperty,value);
                headerLabel.Content = value;
            }
        }
        private static void OnLabelTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            BaloonBox baloonBox = (BaloonBox)d;
            if (string.IsNullOrEmpty(e.NewValue.ToString()))
            {
                if (baloonBox.headerLabel != null) baloonBox.headerLabel.Foreground = Brushes.Gray;
                if (baloonBox.headerLabel != null) baloonBox.headerLabel.Content = baloonBox.WaterMark;
            }
            else
            {
                if (baloonBox.headerLabel != null) baloonBox.headerLabel.Foreground = Brushes.Black;
                if (baloonBox.headerLabel != null) baloonBox.headerLabel.Content = e.NewValue;
            }


        }
        public static readonly DependencyProperty BaloonBoxTypeProperty = DependencyProperty.Register(
            "BaloonBoxType", typeof(BaloonBoxTypeEnum), typeof(BaloonBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnBaloonBoxTypeChanged)));

        public BaloonBoxTypeEnum Type
        {
            get { return (BaloonBoxTypeEnum) GetValue(BaloonBoxTypeProperty);}
            set { SetValue(BaloonBoxTypeProperty,value);}
        }

        private static void OnBaloonBoxTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            //who cares? 
        }
    }
}

                                                                                                                                                                                                             
                            

                    </Border>
                    <Popup x:Name="PART_PopUp" HorizontalOffset="-50" VerticalOffset="-5" AllowsTransparency="True" IsOpen="False" PopupAnimation="Slide" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Header}">
                        <Grid Height="150" Width="250" >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="2"></ColumnDefinition>
                                <ColumnDefinition Width="0.050*"></ColumnDefinition>
                                <ColumnDefinition Width="0.900*"></ColumnDefinition>
                                <ColumnDefinition Width="0.050*"></ColumnDefinition>
                                <ColumnDefinition Width="2"></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="2"></RowDefinition>
                                <RowDefinition Height="0.300*"></RowDefinition>
                                <RowDefinition Height="0.700*"></RowDefinition>
                                <RowDefinition Height="0.100*"></RowDefinition>
                                <RowDefinition Height="2"></RowDefinition>
                            </Grid.RowDefinitions>
                            <Path Grid.Row="1" Grid.RowSpan="3" Grid.Column="1" Grid.ColumnSpan="3" Data="M79,279 L119,279 135,263 135,279 319,279 319,368.5 78.5,368.5 z" Fill="#FFFDFDB3" Stretch="Fill" Stroke="Black" UseLayoutRounding="False">
                            </Path>
                            <ScrollViewer Grid.Row="2" Grid.Column="2" Grid.RowSpan="1" HorizontalScrollBarVisibility="Auto"  VerticalScrollBarVisibility="Auto">
                                <ContentPresenter x:Name="PART_ContenContentControl" Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
                            </ScrollViewer>
                        </Grid>
                    </Popup>
                </Grid>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>