Casella di controllo LED personalizzata WPF

Attualmente sto cercando di “trasferire” un controllo da WindowsForms a WPF. Ho questa elegante casella di controllo a led e cerco di ottenere lo stesso aspetto visivo in wpf. ma non sono in grado di farlo.

Ho cercato molto testa a testa non riesco a trovare una soluzione alle mie domande / problemi.

Ecco come si presenta il controllo delle vinacce inserisci la descrizione dell'immagine qui

La dimensione del cerchio colorato dipende dalla dimensione del controllo. Il colore è definibile dall’utente. Il colore è usato per il cerchio e il testo. È luminoso se è selezionato e distriggersto / grigio quando è deselezionato. I colors di diark e di evidenziazione sono calcolati dal colore di controllo (più chiaro / più scuro).

Tutti i miei tentativi di fare lo stesso in wpf sono quasi falliti fino ad ora. 🙁 Ho provato a farlo con un usercontrol, ma ho deciso che sarebbe stato più semplice ricavarlo dalla casella di controllo con solo un’opzione extra per impostare il colore.

                 

Questo è il mio codice LedControl:

                    

e il codice dietro:

  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 

}

Il fatto è che il controllo non funziona. Ho impostato Color su forrestGreen, ma compare in rosso nel designer e se eseguo il programma:

inserisci la descrizione dell'immagine qui

Il testo “Some Option” non è mostrato anche ..

Non ho capito come avere i colors sfumati per essere versioni più scure e chiare del colore che voglio.

Anche l’aspetto dei led non è così bello come nelle winform, ma non ho la minima idea di tradurre il codice in wpf.

ecco la parte del codice che disegna il led in win-Form:

 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); } } 

Il mio secondo tentativo con la casella di controllo come base è nore o meno inutile, ma forse qualcuno è appassionato e può sostituire la casella di controllo con il led.

Qualsiasi aiuto è apprezzato!

ecco un LedControl derivato da CheckBox. LedControl stesso aggiunge proprietà OnColor e OffColor .

 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); } } } 

e l’aspetto visivo è personalizzato tramite Stile e Modello. Le parti principali del modello sono LedBorder ellisse di LedBorder , l’ellisse di CornerLight bianca, la forma di CornerLight bianca e, naturalmente, ContentPresent. LedBorder adatta all’altezza di LedControl . A seconda di IsChecked LedBorder è colorato con OnColor o OffColor (oltre a Primo piano). Il controllo disabilitato è distriggersto.

  

ed ecco un esempio:

       

inserisci la descrizione dell'immagine qui

È ansible utilizzare PathGradientBrush per disegnare un gradiente radiale. Ecco il risultato del codice che ho scritto. Puoi usare qualsiasi colore come CheckedColor e UnCheckedColor , ho usato Red e Green per ottenere questo risultato:

inserisci la descrizione dell'immagine qui

Codice

 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); } }