I have to assign the class object to the cell of the WPF grid. The class object has one string variable_name. But when I assigned the observablecollection of that particular class, it assign the variable name throughout the particular datagrid row instead of cell. I know that the number of datagrid rows are equal to the number of items present in itemsource assigned collection, but I need to assign to single cell not row. There are many items that I need to assign to each cell but if variable issue is resolved I can modify other code as well.
Screenshot:
public partial class MainWindow : Window
{
public string exp = "A+B";
public class GraphObj: INotifyPropertyChanged
{
string _variable_name = "";
public string variable_name
{
get { return _variable_name; }
set {
_variable_name = value;
OnPropertyChanged("variable_name")
}
}
public GraphObj()
{
variable_name = "A";
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string prop)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
public MainWindow()
{
InitializeComponent();
Rectangle screen = Screen.PrimaryScreen.WorkingArea;
int w = (int)(Width >= screen.Width ? screen.Width : (screen.Width + Width) / 2);
int h = (int)(Height >= screen.Height ? screen.Height : (screen.Height + Height) / 2);
dgGraph.Width = w;
dgGraph.Height = h;
graphObjArray = new ObservableCollection<GraphObj>();
InitilizeDataGrid();
}
private void InitializeDataGrid()
{
for (int j = 0; j < 16; j++)
{
GraphObj obj = new GraphObj();
graphObjArray.Add(obj);
}
DataTemplate d = mygrid.Resources["myTemplate"] as DataTemplate;
for (int i = 0; i < 16; i++)
{
DataGridTemplateColumn tmp2 = new DataGridTemplateColumn();
tmp2.CellTemplate = d;
tmp2.Width = dgGraph.Width / 16;
dgGraph.Columns.Add(tmp2);
}
dgGraph.ItemsSource = graphObjArray;
}
}
XAML:
<Window x:Class="WPF_Grid_Demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
Loaded="Window_Loaded" >
<Grid x:Name="mygrid">
<Grid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="White" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
</Style>
<DataTemplate x:Key="myTemplate" x:Name="mycelltemplate">
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Rectangle Fill= "Blue"/>
</Grid>
<Grid Grid.Column="2">
<Rectangle Fill="Green"/>
</Grid>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<TextBlock Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"
FontWeight="Bold" Text="{Binding variable_name}" />
</Grid>
<Grid Grid.Row="1">
<Image Stretch="UniformToFill" Source="{Binding imgURL}"/>
</Grid>
</Grid>
</Grid>
</DataTemplate>
</Grid.Resources>
<DataGrid x:Name="dgGraph"
GridLinesVisibility="None"
IsReadOnly="True"
AutoGenerateColumns="False"
CanUserResizeRows="False"
CanUserResizeColumns="False"
ScrollViewer.CanContentScroll="False"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
>
</DataGrid>
</Grid>
</Window>
I created a datagrid. I would like to include a custom control in a DataTemplate (CLightSystem). The control works outside of the data grid. In the data grid, the "Value" property is always empty, although StatusDrawing is not empty. What could be the reason for this?
<DataGrid Grid.Row="1" Grid.Column="5"
BorderThickness="3"
ItemsSource="{Binding CncCollectionM12}"
SelectedItem="{Binding SelectedItem}"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="True"
FontSize="16"
Style="{StaticResource MaterialDesignDataGrid}">
<DataGrid.Columns>
<DataGridTemplateColumn Header="M12" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="LIGHT SYSTEM"></TextBlock>
<components:CLightSystem Value="{Binding StatusDrawing}"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
This is the class from the custom control:
public class CLightSystem : Control
{
private Ellipse redLight;
private Ellipse orangeLight;
private Ellipse greenLight;
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(string), typeof(CLightSystem), new PropertyMetadata(default(string)));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
static CLightSystem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CLightSystem), new FrameworkPropertyMetadata(typeof(CLightSystem)));
}
public override void OnApplyTemplate()
{
redLight = Template.FindName("ERedLight", this) as Ellipse;
orangeLight = Template.FindName("EOrangeLight", this) as Ellipse;
greenLight = Template.FindName("EGreenLight", this) as Ellipse;
UpdateLight();
base.OnApplyTemplate();
}
public void UpdateLight()
{
switch (Value)
{
case "GESPERRT":
redLight.Fill = new SolidColorBrush(Colors.Red);
redLight.Effect = new DropShadowEffect()
{
Color = new Color { A = 255, R = 255, G = 0, B = 0 },
BlurRadius = 3,
Direction = -90,
ShadowDepth = 0
};
break;
case "IN BEARBEITUNG":
orangeLight.Fill = new SolidColorBrush(Colors.DarkOrange);
orangeLight.Effect = new DropShadowEffect()
{
Color = new Color { A = 255, R = 255, G = 165, B = 255 },
BlurRadius = 3,
Direction = -90,
ShadowDepth = 0
};
break;
case "FREIGEGEBEN":
greenLight.Fill = new SolidColorBrush(Colors.Green);
greenLight.Effect = new DropShadowEffect()
{
Color = new Color { A = 255, R = 0, G = 255, B = 0 },
BlurRadius = 3,
Direction = -90,
ShadowDepth = 0
};
break;
}
}
}
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Components/DLightSystemStyle.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:components="clr-namespace:Pruefprogramm.Components">
<Style TargetType="components:CLightSystem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="components:CLightSystem">
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" Background="DimGray">
<Ellipse Height="20"
Width="20"
Fill="LightGray"
x:Name="ERedLight"/>
<Ellipse Height="20"
Width="20"
Fill="LightGray"
x:Name="EOrangeLight" />
<Ellipse Height="20"
Width="20"
Fill="LightGray"
x:Name="EGreenLight" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Thank you very much
Levin
If it works outside the DataGrid in the same parent control/window but not inside, it's probably the binding to StatusDrawing that fails.
If this property is defined in the same class as the CncCollectionM12 property, you should bind to it like this:
<components:CLightSystem Value="{Binding DataContext.StatusDrawing,
RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
Suppose I have a list which contains some elements and texts:
public MainWindow()
{
InitializeComponent();
TextBlock t = new TextBlock();
t.Text = "Hello World!";
Ellipse e = new Ellipse();
e.Width = 100;
e.Height = 100;
e.Fill = new SolidColorBrush(Colors.Yellow);
Rectangle r = new Rectangle();
r.Width = 70;
r.Height = 40;
r.Fill = new SolidColorBrush(Colors.Blue);
List<UIElementItem> items = new List<UIElementItem>();
items.Add(new UIElementItem() { uiElement = t, Text = "This is a TextBlock: " });
items.Add(new UIElementItem() { uiElement = e, Text = "This is an Ellipse: " });
items.Add(new UIElementItem() { uiElement = r, Text = "This is a Rectangle: " });
lbListBox.ItemsSource = items;
}
}
public class UIElementItem
{
public UIElement uiElement { get; set; }
public string Text { get; set; }
}
This is the ListBox in XAML:
<ListBox Name="lbListBox" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,2" Orientation="Horizontal">
<TextBlock Text="{Binding Text}"/>
<??? = "{Binding uiElement}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want to make the ListBox show the texts and the elements.
The TextBlock Text="{Binding Text}" will show the text but how to show the element? How to bind?
You could use a ContentPresenter
<ContentPresenter Content="{Binding uiElement}" />
This would show the UI Elements. The complete ItemTemplate would look like
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,2" Orientation="Horizontal">
<TextBlock Text="{Binding Text}"/>
<ContentPresenter Content="{Binding uiElement}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
I currently trying to "port" some control from WindowsForms to WPF.
I Have this stylish led checkbox and try to achieve the same visual appearance in wpf. but I'm unable to get it done.
I've searched a lot butt cannot find a solution to my questions/problems.
This is how the winforms Control looks like
The colored Circle size depends on the size of the control.
The color is user definable. The color is used for the circle and the Text.
It's bright if it ich checked and dimmed / gray when it's unchecked.
The diark and highlight colors are calculated from the control color (lighter/darker).
All my tries to do the same in wpf pretty much failed up to now. :-(
I fist tried to do it with an usercontrol, but decided it would be easier to have it derived from checkbox with just an extra option to set the color.
<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>
This is my LedControl code:
<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>
and the code behind:
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
}
The thing is that the control does not work. I set the Color to forrestGreen, but shows up red in designer and if I execute the program:
The text "Some Option" is not shown as well..
I haven't figured out how to have the gradient colors to be darker and lighter versions of the color I want.
The look of the led is also not as cool as in winforms,
but I have no clue to translate the code to wpf.
here is the part of the code that draws the led in win-Forms:
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);
}
}
My second try with the checkbox as base is nore or less useless, but perhaps someone is keen and can substitute the checkbox with the led.
Any help is appreciated!
here is a LedControl derived from CheckBox. LedControl itself adds OnColor and OffColor properties.
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); }
}
}
and visual appearance is customized via Style and Template. Main template parts are LedBorder ellipse, white CenterGlow ellipse, white CornerLight shape and of course ContentPresent. LedBorder adapts to LedControl height. Depending on IsChecked LedBorder is colored with OnColor or OffColor (as well as Foreground). Disabled control is grayed.
<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>
and here is a sample:
<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>
You can use PathGradientBrush to draw a radial gradient. Here is the result of the code which I wrote. You can use any color as CheckedColor and UnCheckedColor, I used Red and Green to get this result:
Code
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);
}
}
I've created a bar chart via the below code however I'd like to add the red line at some X value as seen in the image below. Is this possible? And if so, how could I accomplish this?
<charting:Chart x:Name="BarChart" HorizontalAlignment="Left" VerticalAlignment="Top" Visibility="Visible" Width="280" Height="500" Margin="-5,-35,0,20" FontSize="10">
<charting:Chart.LegendStyle>
<Style TargetType="datavis:Legend">
<Setter Property="Width" Value="0"/>
</Style>
</charting:Chart.LegendStyle>
<charting:BarSeries Visibility="Visible"/>
<charting:Chart.Palette>
<charting:ResourceDictionaryCollection>
<ResourceDictionary>
<SolidColorBrush x:Key="Background" Color="#2574a9" />
<Style x:Key="DataPointStyle" TargetType="Control">
<Setter Property="Background" Value="{StaticResource Background}" />
</Style>
<Style x:Key="DataShapeStyle" TargetType="Shape">
<Setter Property="Stroke" Value="{StaticResource Background}" />
<Setter Property="StrokeThickness" Value="2" />
<Setter Property="StrokeMiterLimit" Value="1" />
<Setter Property="Fill" Value="{StaticResource Background}" />
</Style>
</ResourceDictionary>
</charting:ResourceDictionaryCollection>
</charting:Chart.Palette>
</charting:Chart>
I wrote a demo to add a line according to the special X value. This feature is implemented by calculating the position of the special X value, and add the Line element. It works and you can test.
XAML Code
<Grid x:Name="rootgrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<charting:Chart
x:Name="BarChart"
Title="Bar Chart"
Width="800"
Height="400">
<charting:BarSeries
x:Name="bar"
Title="Population"
DependentValueBinding="{Binding Value}"
IndependentValueBinding="{Binding Name}"
IsSelectionEnabled="True" />
</charting:Chart>
<StackPanel x:Name="InsertLine" >
<TextBox x:Name="txtnumber" Header="The location for insert a new line" />
<Button
x:Name="getaxi"
Click="getaxi_Click"
Content="Insert the new line" />
</StackPanel>
</Grid>
Code behind
public sealed partial class BarChat : Page
{
private Random _random = new Random();
private LinearAxis linearaxis;
private CategoryAxis categoryaxis;
private double linearaximaximum;
private double linearaximinimum;
private Line newline;
public BarChat()
{
this.InitializeComponent();
Window.Current.SizeChanged += Current_SizeChanged; ;
var items1 = new List<NameValueItem>();
for (int i = 0; i < 3; i++)
{
items1.Add(new NameValueItem { Name = "Name" + i, Value = _random.Next(1, 100) });
}
this.RunIfSelected(this.BarChart, () => ((BarSeries)this.BarChart.Series[0]).ItemsSource = items1);
}
private void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
if (rootgrid.Children.Contains(newline))
{
clearline();
if (txtnumber.Text != null)
{
var insertvalue = Convert.ToDouble(txtnumber.Text);
positionline(insertvalue);
}
}
}
public void barchartinihital()
{
var Actualaxes = BarChart.ActualAxes;
linearaxis = Actualaxes[1] as LinearAxis;
categoryaxis = Actualaxes[0] as CategoryAxis;
linearaximaximum = Convert.ToDouble(linearaxis.ActualMaximum);
linearaximinimum = Convert.ToDouble(linearaxis.ActualMinimum);
}
private void RunIfSelected(UIElement element, Action action)
{
action.Invoke();
}
private async void getaxi_Click(object sender, RoutedEventArgs e)
{
clearline();
barchartinihital();
if (txtnumber.Text != null)
{
double insertvalue = Convert.ToDouble(txtnumber.Text);
if (insertvalue > linearaximaximum || insertvalue < linearaximinimum)
{
await new Windows.UI.Popups.MessageDialog("Please input a value in chart arrange").ShowAsync();
}
else
{
positionline(insertvalue);
}
}
}
public void positionline(double insertvalue)
{
var interval = linearaxis.ActualInterval;
double perinterval = Convert.ToDouble(linearaxis.ActualWidth / (linearaximaximum - linearaximinimum));
var lineX = perinterval * (insertvalue - linearaximinimum);
var lineheight = categoryaxis.ActualHeight;
var ttv = bar.TransformToVisual(Window.Current.Content);
Point screenCoords = ttv.TransformPoint(new Point(0, 0));
var chartx = screenCoords.X;
var charty = screenCoords.Y;
newline = new Line();
newline.X1 = Convert.ToDouble(lineX) + chartx;
newline.X2 = Convert.ToDouble(lineX) + chartx;
newline.Y1 = charty;
newline.Y2 = charty + lineheight;
newline.Stroke = new SolidColorBrush(Colors.Red);
newline.StrokeThickness = 2;
rootgrid.Children.Add(newline);
}
public void clearline()
{
if (rootgrid.Children.Contains(newline))
{
{
rootgrid.Children.Remove(newline);
}
}
}
}