c# - ComboBox 的水印行为

标签 c# wpf combobox

我目前有一个 combobox绑定(bind)到 dictionary .我想做的是在 combobox 中有一个默认项,例如“请选择一个项目...”,当用户实际点击 combobox 时它会消失选择一个项目。

我在这个网站上看到过类似的问题,但似乎无法找到任何适合我的解决方案。我唯一的幸运是将其放入我的 xaml 组合框代码中:

<IsEditable="True" IsReadOnly="True" Text="Please select an item..."/>

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

我的代码背后:

private Dictionary<string, string> imageTypes = new Dictionary<string, string>();

public MainWindow()
{
    InitializeComponent();
    AddImage_Types();
}

public void AddImage_Types()
{
    imageTypes.Add("*.png", Png);
    imageTypes.Add("*.jpg *.jpeg *jfif", Jpg);
}

public Dictionary<string, string> ImageTypes
{
    get
    {
        return imageTypes;
    }
}

这是我的组合框 xaml:

<ComboBox Name="imageCB"
          ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=ImageTypes}"
          SelectedValuePath="Value"
          DisplayMemberPath="Key" >
</ComboBox>

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

我确定这很简单,但我似乎无法理解。

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

最佳答案

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

Watermark Behavior

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

2- 在你的 xaml 中声明它

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

3- 将这个类添加到您的项目中

public class WatermarkBehavior : Behavior<ComboBox>
{
    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:

<ComboBox Width="200" IsEditable="True" IsReadOnly="True">
    <i:Interaction.Behaviors>
        <local:WatermarkBehavior Text="Please select..." />
    </i:Interaction.Behaviors>
    <ComboBoxItem>Item1</ComboBoxItem>
    <ComboBoxItem>Item2</ComboBoxItem>
    <ComboBoxItem>Item3</ComboBoxItem>
</ComboBox>

关于c# - ComboBox 的水印行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37211869/

相关文章:

c# - 使用 C# 在 asp.net 中以 Word 格式转换货币格式的 int 值?

wpf - 错误 XLS0502 'WindowsFormsHost' 类型不支持直接内容

c# - 在 WPF 中的 MediaElement 顶部呈现按钮

c# - 绑定(bind)到列表的动态文本框

mysql - 组合框并从数据网格显示

c# - .NET 中未测试类的依赖注入(inject)

c# - 发送电子邮件附件后删除 c# 中的文件

c# - Office 互操作无法在多台计算机上运行

java - SetAlignment 方法在带有组合框的 FlowLayout 中不起作用

if语句中的VBA屏幕更新