我想通过使用带有额外元素的模板和插入在正确位置的原始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>
结果只是一个绿色框,应该是我的文本框空间!
答案 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>