2017-03-17 5 views
2

現在、私はいくつかのコントロールをWindowsフォームからWPFに「移植」しようとしています。 私はこのスタイリッシュなledチェックボックスを持って、wpfで同じ外観を実現しようとします。私はそれを行うことができません。WPFカスタムLEDチェックボックス

私はたくさんの検索をしましたが、私の質問/問題の解決策を見つけることができません。

これは、色付きの円の大きさは、コントロールのサイズに依存

enter image description here ようWinFormsのコントロールがどのように見えるかです。 色はユーザー定義可能です。色は円とテキストに使用されます。 未チェックの場合は明るく、灰色/グレーの場合はグレーです。 ダイアマークとハイライトの色は、コントロールの色(明/暗)から計算されます。

私はwpfで同じことをやろうとしていましたが、これまでほとんど失敗しました。 。

:私は、ユーザーコントロールでそれを実行しようとしましたが、それは色を設定するだけで、余分なオプションでチェックボックス由来持つことが容易になるだろうことを決めた

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   
    xmlns:test="clr-namespace:LedTest" 
    xmlns:uc="clr-namespace:WPFTest;assembly=LedControl" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    x:Class="LedTest.MainWindow" 
    Title="MainWindow" Height="285" Width="566"> 
    <Window.Resources> 
     <ResourceDictionary x:Key="ResDict2" Source="Dictionary2.xaml"/> 
    </Window.Resources> 
    <Grid Margin="0"> 
     <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" MinHeight="27" /> 
     <RowDefinition Height="75"/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="10*" /> 
     <ColumnDefinition Width="179*"/> 
     </Grid.ColumnDefinitions> 
     <uc:LedControl x:Name="led1" 
      Color="ForestGreen" Text="Some Option" 
     Grid.Column="1" Grid.Row="1" Height="39" VerticalAlignment="Bottom" Margin="0,0,0,36"/> 
     <CheckBox Content="Some Option" Style="{DynamicResource TestStyle}" Margin="0,0,31,0" Grid.Column="1"/> 
    </Grid> 
</Window> 

これは私のLedControlコードで拳:-(

<UserControl x:Class="LedControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="100" d:DesignWidth="300"> 
    <UserControl.Resources> 
    </UserControl.Resources> 
    <StackPanel x:Name="gridBigLed" Orientation="Horizontal" > 
     <Border x:Name="border1" 
       BorderThickness="1" 
       Width="{Binding ActualHeight, ElementName=gridBigLed, Mode=OneWay}" 
       CornerRadius="{Binding ActualWidth, ElementName=gridBigLed, Mode=OneWay}" 
       HorizontalAlignment="Left"> 
     <Border.Background> 
      <RadialGradientBrush GradientOrigin="0.2,0.2"> 
       <GradientStop Color="#FFFFAAAA"/> 
       <GradientStop x:Name="backgroundColor" Color="Red" Offset="1.2"/> 
      </RadialGradientBrush> 
     </Border.Background> 
     <Border.BorderBrush> 
      <RadialGradientBrush> 
       <GradientStop x:Name="GradientColorLow" Color="#FF660000" Offset="0.383"/> 
       <GradientStop x:Name="GradientColorHigh" Color="#330000" Offset="0.5"/> 
      </RadialGradientBrush> 
     </Border.BorderBrush> 
     </Border> 
     <Label Content="{Binding Text}" x:Name="LEDText" Foreground="Red" HorizontalContentAlignment="Left" VerticalContentAlignment="Center"/> 
    </StackPanel> 
</UserControl> 

と後ろコード:

 public partial class LedControl : UserControl 
    { 
     #region Dependency properties 
     /// <summary>Dependency property to Get/Set the current IsActive (True/False)</summary> 
     public static readonly DependencyProperty IsCheckedProperty = 
      DependencyProperty.Register("IsChecked", typeof(bool?), typeof(LedControl), 
       new PropertyMetadata(null, new PropertyChangedCallback(LedControl.IsCheckedPropertyChanced))); 

     /// <summary>Dependency property to Get/Set Color when IsActive is true</summary> 
     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 
     /// <summary>Gets/Sets Text Value</summary> 
     public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } 
     /// <summary>Gets/Sets Value</summary> 
     public bool? IsChecked { get { return (bool?)GetValue(IsCheckedProperty); } set { SetValue(IsCheckedProperty, value); } } 
     /// <summary>Gets/Sets Color</summary> 
     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 

}

問題は、コントロールが機能しないことです。私はforrestGreenに色を設定しますが、デザイナーで赤く表示され、私はプログラムを実行している場合:

enter image description here

テキスト「いくつかのオプションは、」

私はそうではありません。..としても示されていませんどのようにグラデーションの色をより暗く、私が欲しい色の明るいバージョンにするかを考え出しました。

LEDの外観も、winformsのようにクールではありませんが、 ですが、コードをwpfに翻訳する手がかりはありません。ここ

は勝利 - フォームで主導ドローコードの一部です:

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

    } 

ベースとしてチェックボックスと私の2回目の試行は、NORE以下役に立たないですが、おそらく誰かが熱心であると置き換えることができますリードとチェックボックス。

ご協力いただきましてありがとうございます。

答えて

2

はCheckBoxの由来LedControlです:あなたは、私はこの結果を得るためにRedGreenを使用し、CheckedColorUnCheckedColorとして任意の色を使用することができます。 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です。 LedBorderLedControlの高さに適合します。 IsCheckedLedBorderに応じて、OnColorまたはOffColor(またはフォアグラウンド)で色付けされています。無効なコントロールはグレー表示されます。

<Style TargetType="local:LedControl"> 
    <Setter Property="VerticalContentAlignment" Value="Center"/> 
    <Setter Property="BorderBrush" Value="Black"/> 
    <Setter Property="Margin" Value="5"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="local:LedControl"> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition/> 
        </Grid.ColumnDefinitions> 

        <Grid Background="Transparent" Name="grd" 
          Margin="{TemplateBinding Padding}" 
          VerticalAlignment="Stretch" 
          Width="{Binding Path=ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Self}}"> 

         <Ellipse x:Name="LedBorder" 
            Fill="{TemplateBinding Background}" 
            Stroke="{TemplateBinding BorderBrush}" 
            StrokeThickness="2" 
            Stretch="Uniform"/> 

         <Ellipse x:Name="CenterGlow" Stretch="Uniform"> 
          <Ellipse.Fill> 
           <RadialGradientBrush> 
            <GradientStop Color="White" Offset="-0.25"/> 
            <GradientStop Color="Transparent" Offset="0.91"/> 
           </RadialGradientBrush> 
          </Ellipse.Fill> 
         </Ellipse> 

         <Ellipse x:Name="CornerLight" Stretch="Uniform" Margin="2"> 
          <Ellipse.Fill> 
           <RadialGradientBrush Center="0.15 0.15" RadiusX="0.5" RadiusY="0.5"> 
            <GradientStop Color="White" Offset="0"/> 
            <GradientStop Color="Transparent" Offset="1"/> 
           </RadialGradientBrush> 
          </Ellipse.Fill> 
         </Ellipse> 
        </Grid> 

        <ContentPresenter x:Name="content" Grid.Column="1" Margin="4,0,0,0" 
          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
          RecognizesAccessKey="True"/> 

       </Grid> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsChecked" Value="true"> 
         <Setter TargetName="LedBorder" Property="Fill" Value="{Binding Path=OnColor, RelativeSource={RelativeSource TemplatedParent}}"/> 
         <Setter TargetName="content" Property="TextElement.Foreground" Value="{Binding Path=OnColor, RelativeSource={RelativeSource TemplatedParent}}"/> 
        </Trigger> 

        <Trigger Property="IsChecked" Value="false"> 
         <Setter TargetName="LedBorder" Property="Fill" Value="{Binding Path=OffColor, RelativeSource={RelativeSource TemplatedParent}}"/> 
         <Setter TargetName="content" Property="TextElement.Foreground" Value="{Binding Path=OffColor, RelativeSource={RelativeSource TemplatedParent}}"/> 
        </Trigger> 

        <Trigger Property="IsEnabled" Value="false"> 
         <Setter TargetName="CenterGlow" Property="Fill"> 
          <Setter.Value> 
           <RadialGradientBrush Opacity="1"> 
            <GradientStop Color="Transparent" Offset="-0.5" /> 
            <GradientStop Color="#888" Offset="1" /> 
           </RadialGradientBrush> 
          </Setter.Value> 
         </Setter> 
         <Setter TargetName="content" Property="TextElement.Foreground" Value="#888"/> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

、ここのサンプルです:

<StackPanel> 
    <local:LedControl Content="Disabled OFF" Height="24" IsChecked="False" IsEnabled="False" /> 
    <local:LedControl Content="Disabled ON" Height="32" IsChecked="True" IsEnabled="False" /> 
    <local:LedControl Content="Enabled OFF" OffColor="Chocolate" IsChecked="False" Height="40" /> 
    <local:LedControl Content="Enabled ON" OnColor="Navy" IsChecked="True" Height="48" /> 
</StackPanel> 

enter image description here

+0

あなたの知識を共有してくれてありがとう。私は私のニーズに合うようにいくつかの修正を行いましたが、実際にはこれが私の必要なものでした。 –

2

PathGradientBrushを使用すると、ラジアルグラデーションを描画できます。ここに私が書いたコードの結果があります。ここ

enter image description here

コード

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

これは一見かなりクールに見えます。私は休日の後にそれをチェックします。だから私にそれのための時間を与えてください。 –

+2

WindowsフォームでLED CheckBoxを作成して答えを投稿したと思っていますが、その逆も必要です。しかし、私はそれがエレガントなWindowsフォームLEDチェックボックスだと思うので、私はコードを保持することを好む。 –

+0

気にしないでください。私はまず、これが行く方法だと思った。しかし、あなたはそれが窓のフォームと述べた。しかし、私はwpfのためにそれが必要です。 –

関連する問題