WPF自定义LED复选框

我目前正试图将一些控件从WindowsForms“移植”到WPF。 我有这个时尚的led复选框,并尝试在wpf中实现相同的视觉外观。 但我无法完成它。

我搜索了很多但是找不到我的问题/问题的解决方案。

这就是winforms Control的样子 在此处输入图像描述

彩色圆圈大小取决于控件的大小。 颜色是用户可定义的。 颜色用于圆和文本。 如果在未经检查的情况下检查并调暗/灰色,它会很亮。 从控制颜色(更亮/更暗)计算diark和高亮颜色。

我所有尝试在wpf中做同样的事情到目前为止都失败了。 :-(我的拳头尝试用usercontrol做,但决定从复选框派生它只是一个额外的选项来设置颜色会更容易。

                 

这是我的LedControl代码:

                    

和背后的代码:

  public partial class LedControl : UserControl { #region Dependency properties /// Dependency property to Get/Set the current IsActive (True/False) public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof(bool?), typeof(LedControl), new PropertyMetadata(null, new PropertyChangedCallback(LedControl.IsCheckedPropertyChanced))); /// Dependency property to Get/Set Color when IsActive is true public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(LedControl), new PropertyMetadata(Colors.Green, new PropertyChangedCallback(LedControl.OnColorPropertyChanged))); public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(LedControl), new PropertyMetadata("ButtonText", new PropertyChangedCallback(LedControl.OnTextPropertyChanged))); #endregion #region Properties /// Gets/Sets Text Value public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } /// Gets/Sets Value public bool? IsChecked { get { return (bool?)GetValue(IsCheckedProperty); } set { SetValue(IsCheckedProperty, value); } } /// Gets/Sets Color public Color Color { get { return (Color)GetValue(ColorProperty); } set { SetValue(ColorProperty, value); } } #endregion #region Constructor public LedControl() { InitializeComponent(); if (this.IsChecked == true) { this.LEDColor.Color = this.Color; this.LEDText.Foreground = new SolidColorBrush(this.Color); } else if (this.IsChecked == false) { this.LEDColor.Color = Colors.Gray; this.LEDText.Foreground = new SolidColorBrush(Colors.Gray); } } #endregion #region Callbacks private static void IsCheckedPropertyChanced(DependencyObject d, DependencyPropertyChangedEventArgs e) { LedControl led = (LedControl)d; if (led.IsChecked == true) { led.LEDColor.Color = led.Color; led.LEDText.Foreground = new SolidColorBrush(led.Color); } else { led.LEDColor.Color = Colors.Gray; // TODO calculate dark/gray color led.LEDText.Foreground = new SolidColorBrush(Colors.Gray); } } private static void OnColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { LedControl led = (LedControl)d; led.Color = (Color)e.NewValue; if (led.IsChecked == true) { led.LEDColor.Color = led.Color; led.LEDText.Foreground = new SolidColorBrush( led.Color ); } } private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { LedControl led = (LedControl)d; led.Text = (String)e.NewValue; } #endregion 

}

问题是控件不起作用。 我将Color设置为forrestGreen,但在设计器中显示红色,如果我执行该程序:

在此处输入图像描述

文本“Some Option”也没有显示..

我还没弄明白如何让渐变色变成我想要的颜色更暗更亮的版本。

led的外观也不像winforms那样酷,但我不知道将代码转换为wpf。

这是在win-Forms中绘制led的代码的一部分:

 private void drawControl(Graphics g, bool on) { // Is the bulb on or off Color lightColor = (on) ? this.Color : Color.FromArgb(100, this.Color); Color darkColor = (on) ? this.DarkColor : Color.Gray/*this.DarkDarkColor*/; // Calculate the dimensions of the bulb int width = this.Width - (this.Padding.Left + this.Padding.Right); int height = this.Height - (this.Padding.Top + this.Padding.Bottom); // Diameter is the lesser of width and height int diameter = Math.Min(width, height); // Subtract 1 pixel so ellipse doesn't get cut off diameter = Math.Max(diameter - 1, 1); SolidBrush br = new SolidBrush(BackColor); g.FillRectangle(br, ClientRectangle); // Draw the background ellipse var rectangle = new Rectangle(this.Padding.Left, this.Padding.Top, diameter, diameter); g.FillEllipse(new SolidBrush(darkColor), rectangle); // Draw the glow gradient var path = new GraphicsPath(); path.AddEllipse(rectangle); var pathBrush = new PathGradientBrush(path); pathBrush.CenterColor = lightColor; pathBrush.SurroundColors = new Color[] { Color.FromArgb(0, lightColor) }; g.FillEllipse(pathBrush, rectangle); // Draw the white reflection gradient var offset = Convert.ToInt32(diameter * .15F); var diameter1 = Convert.ToInt32(rectangle.Width * .8F); var whiteRect = new Rectangle(rectangle.X - offset, rectangle.Y - offset, diameter1, diameter1); var path1 = new GraphicsPath(); path1.AddEllipse(whiteRect); var pathBrush1 = new PathGradientBrush(path); pathBrush1.CenterColor = _reflectionColor; pathBrush1.SurroundColors = _surroundColor; g.FillEllipse(pathBrush1, whiteRect); // Draw the border g.SetClip(this.ClientRectangle); if (this.On) g.DrawEllipse(new Pen(Color.FromArgb(85, Color.Black),1F), rectangle); if (this.Text != string.Empty) { RectangleF textArea = this.ClientRectangle; textArea.X += rectangle.Width + 6; textArea.Width -= (diameter + 6); Font fon = new Font(Font.FontFamily, Font.Size-1, FontStyle.Bold); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Near; sf.LineAlignment = StringAlignment.Center; if (!this.On) g.DrawString(this.Text, fon, new SolidBrush(Color.Gray), textArea, sf); else g.DrawString(this.Text, fon, new SolidBrush(darkColor), textArea, sf); } } 

我以复选框为基础的第二次尝试是无用的或者更少无用,但也许有人很热衷并且可以用led替换复选框。

任何帮助表示赞赏!

这是一个从CheckBox派生的LedControl。 LedControl本身添加了OnColorOffColor属性。

 public class LedControl : CheckBox { static LedControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(LedControl), new FrameworkPropertyMetadata(typeof(LedControl))); } public static readonly DependencyProperty OnColorProperty = DependencyProperty.Register("OnColor", typeof(Brush), typeof(LedControl), new PropertyMetadata(Brushes.Green)); public Brush OnColor { get { return (Brush)GetValue(OnColorProperty); } set { SetValue(OnColorProperty, value); } } public static readonly DependencyProperty OffColorProperty = DependencyProperty.Register("OffColor", typeof(Brush), typeof(LedControl), new PropertyMetadata(Brushes.Red)); public Brush OffColor { get { return (Brush)GetValue(OffColorProperty); } set { SetValue(OffColorProperty, value); } } } 

并通过样式和模板自定义视觉外观。 主要模板部分是LedBorder椭圆,白色CenterGlow椭圆,白色CornerLight形状,当然还有ContentPresent。 LedBorder适应LedControl高度。 取决于IsChecked LedBorder使用OnColorOffColor (以及前景)着色。 禁用控件呈灰色。

  

这是一个示例:

       

在此处输入图像描述

您可以使用PathGradientBrush绘制径向渐变。 这是我写的代码的结果。 您可以使用任何颜色作为CheckedColorUnCheckedColor ,我使用RedGreen来获得此结果:

在此处输入图像描述

 using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; public class MyCheckBox : CheckBox { public MyCheckBox() { this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.DoubleBuffered = true; this.ResizeRedraw = true; CheckedColor = Color.Green; ; UnCheckedColor = Color.Red; ; } [DefaultValue(typeof(Color), "Green")] public Color CheckedColor { get; set; } [DefaultValue(typeof(Color), "Red")] public Color UnCheckedColor { get; set; } protected override void OnPaint(PaintEventArgs e) { var darkColor = Color.Black; var lightColor = Color.FromArgb(200, Color.White); var cornerAlpha = 80; this.OnPaintBackground(e); using (var path = new GraphicsPath()) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; var rect = new Rectangle(0, 0, Height, Height); path.AddEllipse(rect); rect.Inflate(-1, -1); using (var bgBrush = new SolidBrush(darkColor)) { e.Graphics.FillEllipse(bgBrush, rect); } using (var pathGrBrush = new PathGradientBrush(path)) { var color = Checked ? CheckedColor : UnCheckedColor; pathGrBrush.CenterColor = color; ; Color[] colors = { Color.FromArgb(cornerAlpha, color) }; pathGrBrush.SurroundColors = colors; e.Graphics.FillEllipse(pathGrBrush, rect); } using (var pathGrBrush = new PathGradientBrush(path)) { pathGrBrush.CenterColor = lightColor; ; Color[] colors = { Color.Transparent }; pathGrBrush.SurroundColors = colors; var r = (float)(Math.Sqrt(2) * Height / 2); var x = r / 8; e.Graphics.FillEllipse(pathGrBrush, new RectangleF(-x, -x, r, r)); e.Graphics.ResetClip(); } } TextRenderer.DrawText(e.Graphics, Text, Font, new Rectangle(Height, 0, Width - Height, Height), ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter); } }