【问题标题】:WPF Template: AdornedElement not showing!WPF 模板:AdornedElement 未显示!
【发布时间】:2010-04-20 12:56:41
【问题描述】:

我想通过使用带有额外元素的模板和插入正确位置的原始文本框来向文本框添加一些元素。我正在尝试使用 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>  

结果只是在应该是我的文本框的空间周围出现一个绿色框!

【问题讨论】:

    标签: wpf silverlight templates controltemplate adorner


    【解决方案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 属性。当然,我真的不知道你到底想要什么。

    -- 高温高压 尘土飞扬

    【讨论】:

    • 我真正想做的是制作一个气球弹出框,使我能够在文本框中写入比 UI 空间更多的文本。我想这样做,同时仍然能够在 xaml 中设置文本框的原始属性,如果我使用“文本”依赖属性制作自定义控件,我不确定是否可以做到这一点(我会丢失 Forecolor , fontstrength 等等。我只是为了简单起见做了个border-example。谢谢你的回复!我会去试试的!
    • 这可能有效,但我需要参考原始文本框来制作一些鼠标悬停事件。我可能需要做一个从文本框继承的用户控件?如果它与 AdornedElementPlaceholder 一起使用,我会很整洁。
    • 使用基于 TextBox 的自定义控件可能是实现目标的最直接方法。另一种方法可能是实际使用 Adorner:msdn.microsoft.com/en-us/library/ms743737.aspx 它们实际上是一个非常强大的概念。也许,如果你有一个与你正在尝试做的事情相似的屏幕截图,我可以提供更多帮助。
    【解决方案2】:

    我最终做了一个基于 HeaderedContent 控件的自定义控件。

    它将允许用户单击或悬停在某些内容上,然后显示包含其他或相同内容的气泡。

    用法:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-08
      • 2018-09-23
      • 2018-09-02
      • 2019-09-03
      • 2015-10-28
      • 1970-01-01
      • 2023-03-28
      相关资源
      最近更新 更多