ComboBox的水印行为

我目前有一个绑定到dictionarycombobox 。 我要做的是在combobox有一个默认项目,例如“请选择一个项目…”,当用户实际点击combobox选择项目时,该项目会消失。

我在这个网站上看到过类似的问题,但似乎无法让任何解决方案适合我。 我唯一的运气就是把它放在我的xamlcombobox代码中:

  

但这当然会改变combobox的外观,我不希望它看起来像是可编辑的。

我的代码背后:

 private Dictionary imageTypes = new Dictionary(); public MainWindow() { InitializeComponent(); AddImage_Types(); } public void AddImage_Types() { imageTypes.Add("*.png", Png); imageTypes.Add("*.jpg *.jpeg *jfif", Jpg); } public Dictionary ImageTypes { get { return imageTypes; } } 

这是我的combobox的xaml:

   

我尝试过使用触发器和样式,就像这个答案: https : //stackoverflow.com/a/16782339/2480598

我确信它很简单,但我似乎无法得到它。

注意:默认情况下,我的意思是当窗口加载时,一些文本已经显示在combobox中,如“请选择项目…”。 当用户单击combobox以从下拉列表中选择项目时,这将消失。

你想要这样做的方式并不是WPF的工作原理。 执行此操作的最佳方法是使用数据validation/绑定,因此用户无法继续前进,直到选择了某些内容; 如果用户没有选择某些东西,或者甚至只是在那里给出一个默认值,则抛出validation错误(combobox周围的红线)。

但是,如果您希望它以您要求的方式工作,您可以:

a)在你的字典中有“请选择一个项目…”,然后在用户选择其他内容时让事件处理程序将其删除

b)将“请选择项目…”作为绑定字典中的唯一项目,然后让事件处理程序在用户打开combobox时更改绑定

c)在combobox的顶部放置一个带有透明背景的标签,当点击时,它会消失

d)(未经测试),如何从此链接调整代码?:

            First item Another item  

查看TextBox的这个示例。 你可以为ComboBox做同样的事情:

水印行为

1-添加对程序集System.Windows.Interactivity的引用

2-在你的xaml中声明这一点

 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 

3-将此类添加到项目中

 public class WatermarkBehavior : Behavior { private WaterMarkAdorner adorner; public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } // Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc... public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(WatermarkBehavior), new PropertyMetadata("Watermark")); public double FontSize { get { return (double)GetValue(FontSizeProperty); } set { SetValue(FontSizeProperty, value); } } // Using a DependencyProperty as the backing store for FontSize. This enables animation, styling, binding, etc... public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(WatermarkBehavior), new PropertyMetadata(12.0)); public Brush Foreground { get { return (Brush)GetValue(ForegroundProperty); } set { SetValue(ForegroundProperty, value); } } // Using a DependencyProperty as the backing store for Foreground. This enables animation, styling, binding, etc... public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register("Foreground", typeof(Brush), typeof(WatermarkBehavior), new PropertyMetadata(Brushes.Black)); public string FontFamily { get { return (string)GetValue(FontFamilyProperty); } set { SetValue(FontFamilyProperty, value); } } // Using a DependencyProperty as the backing store for FontFamily. This enables animation, styling, binding, etc... public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register("FontFamily", typeof(string), typeof(WatermarkBehavior), new PropertyMetadata("Segoe UI")); protected override void OnAttached() { adorner = new WaterMarkAdorner(this.AssociatedObject, this.Text, this.FontSize, this.FontFamily, this.Foreground); this.AssociatedObject.Loaded += this.OnLoaded; this.AssociatedObject.GotFocus += this.OnFocus; this.AssociatedObject.LostFocus += this.OnLostFocus; } private void OnLoaded(object sender, RoutedEventArgs e) { if (!this.AssociatedObject.IsFocused) { if (String.IsNullOrEmpty(this.AssociatedObject.Text)) { var layer = AdornerLayer.GetAdornerLayer(this.AssociatedObject); layer.Add(adorner); } } } private void OnLostFocus(object sender, RoutedEventArgs e) { if (String.IsNullOrEmpty(this.AssociatedObject.Text)) { try { var layer = AdornerLayer.GetAdornerLayer(this.AssociatedObject); layer.Add(adorner); } catch { } } } private void OnFocus(object sender, RoutedEventArgs e) { var layer = AdornerLayer.GetAdornerLayer(this.AssociatedObject); layer.Remove(adorner); } protected override void OnDetaching() { base.OnDetaching(); } public class WaterMarkAdorner : Adorner { private string text; private double fontSize; private string fontFamily; private Brush foreground; public WaterMarkAdorner(UIElement element, string text, double fontsize, string font, Brush foreground) : base(element) { this.IsHitTestVisible = false; this.Opacity = 0.6; this.text = text; this.fontSize = fontsize; this.fontFamily = font; this.foreground = foreground; } protected override void OnRender(System.Windows.Media.DrawingContext drawingContext) { base.OnRender(drawingContext); var text = new FormattedText( this.text, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new System.Windows.Media.Typeface(fontFamily), fontSize, foreground); drawingContext.DrawText(text, new Point(3, 3)); } } } 

4-并添加您的ComboBox:

     Item1 Item2 Item3  

好的,这是我的版本,几乎与Anime提供的版本相同。 我做了一些更改:添加了Margin依赖属性,以便能够将水印定位到我需要的位置。 完全限定的一些对象,因为我的VS感到困惑,并用另一个覆盖替换了一个已弃用的方法。 我还更改了OnFocus事件处理程序,因此当控件获得焦点时,文本实际上会消失。 可能不是通用的,但适用于我的场景。

它来了:

 public class WatermarkBehavior : Behavior { private WaterMarkAdorner adorner; public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(WatermarkBehavior), new PropertyMetadata("Watermark")); public double FontSize { get { return (double)GetValue(FontSizeProperty); } set { SetValue(FontSizeProperty, value); } } public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(WatermarkBehavior), new PropertyMetadata(12.0)); public System.Windows.Media.Brush Foreground { get { return (System.Windows.Media.Brush)GetValue(ForegroundProperty); } set { SetValue(ForegroundProperty, value); } } public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register("Foreground", typeof(System.Windows.Media.Brush), typeof(WatermarkBehavior), new PropertyMetadata(System.Windows.Media.Brushes.Black)); public string FontFamily { get { return (string)GetValue(FontFamilyProperty); } set { SetValue(FontFamilyProperty, value); } } public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register("FontFamily", typeof(string), typeof(WatermarkBehavior), new PropertyMetadata("Segoe UI")); public Thickness Margin { get { return (Thickness)GetValue(MarginProperty); } set { SetValue(MarginProperty, value); } } public static readonly DependencyProperty MarginProperty = DependencyProperty.Register("Margin", typeof(Thickness), typeof(WatermarkBehavior)); protected override void OnAttached() { adorner = new WaterMarkAdorner(this.AssociatedObject, this.Text, this.FontSize, this.FontFamily, this.Margin, this.Foreground); this.AssociatedObject.Loaded += this.OnLoaded; this.AssociatedObject.GotFocus += this.OnFocus; this.AssociatedObject.LostFocus += this.OnLostFocus; } private void OnLoaded(object sender, RoutedEventArgs e) { if (!this.AssociatedObject.IsFocused) { if (String.IsNullOrEmpty(this.AssociatedObject.Text)) { var layer = AdornerLayer.GetAdornerLayer(this.AssociatedObject); layer.Add(adorner); } } } private void OnLostFocus(object sender, RoutedEventArgs e) { if (String.IsNullOrEmpty(this.AssociatedObject.Text)) { try { var layer = AdornerLayer.GetAdornerLayer(this.AssociatedObject); layer.Add(adorner); } catch { } } } private void OnFocus(object sender, RoutedEventArgs e) { if (AssociatedObject.SelectedItem != null) { var layer = AdornerLayer.GetAdornerLayer(this.AssociatedObject); layer.Remove(adorner); } } protected override void OnDetaching() { base.OnDetaching(); } public class WaterMarkAdorner : Adorner { private string text; private double fontSize; private string fontFamily; private System.Windows.Media.Brush foreground; public WaterMarkAdorner(UIElement element, string text, double fontsize, string font, Thickness margin, System.Windows.Media.Brush foreground) : base(element) { this.IsHitTestVisible = false; this.Opacity = 0.6; this.text = text; this.fontSize = fontsize; this.fontFamily = font; this.foreground = foreground; this.Margin = margin; } protected override void OnRender(System.Windows.Media.DrawingContext drawingContext) { base.OnRender(drawingContext); Matrix m = PresentationSource.FromVisual(Application.Current.MainWindow).CompositionTarget.TransformToDevice; var text = new FormattedText( this.text, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(fontFamily), fontSize, foreground, m.M11); drawingContext.DrawText(text, new System.Windows.Point(3, 3)); } } }