Label animation on data change - c#

I need to change to background color animation of a label based on the value of an integer.
MyInt = 1 then label1.background color = Red
MyInt = 2 then label1.background color = Green
MyInt = 3 then label1.background color = Yellow
Can somebody point me in the right direction as I’m completely new to WPF.
Many Thanks

You can use DataTriggers to change properties based on a bound value. The easiest way would be to add a style to your label.

Related

How to Get the font color of an Excel Cell in c#

okay, so I'm trying to get the cell's font color as the program needs to do different things biased on the font color in the cell so I made a test file
and I tried to access it like so:
Range thrange = ws.UsedRange.Columns["A:A", Type.Missing].Rows;
foreach (Range r in thrange)
{
Style sy = r.Style;
Font font = sy.Font;
ColorFormat color = (ColorFormat)font.Color;
Console.WriteLine(" "+r.Value+" " + color.RGB);
}
I get
Can not convert type 'double' to 'Microsoft.Office.Interop.Excel.ColorFormat'
I saw people saying you set the color with a drawing object so I tried changing the last two lines to:
Color color =(System.Drawing.Color)font.Color;
Console.WriteLine(" "+r.Value+" " + color.ToArgb());
but that didn't work either
Can not convert type 'double' to 'System.Drawing.Color'
so I thought I'd see what this double is, then set the font to a known rgb value and work out how to convert the number I get back into that. but that didn't work either.
as while
Console.WriteLine(" "+r.Value+" "+r.style.font.color);
didn't throw an error it still didn't give me anything useful:
cyan 0
pink 0
blue 0
red 0
orange 0
purple 0
I thought maybe r.style.font.colorindex but that just gave me a 1 for everything instead of a 0
I was hopping for something like
blue 0000ff
red ff0000
I can't use a 3rd party libraries due to the rules set out by the project owner.
So how do I get the actual color value out?
Use the Font property of the Range not that of its Style. Then use the ColorTranslator class to convert the double value from Office to a .net Color.
foreach (Microsoft.Office.Interop.Excel.Range r in thrange)
{
// Get Color from Font from Range directly
int oleColor = Convert.ToInt32(r.Font.Color);
// Convert to C# Color type
System.Drawing.Color c = System.Drawing.ColorTranslator.FromOle(oleColor);
// Output
Console.WriteLine(r.Value + " " + c.ToString());
}

WPF Binding Without XAML

I have a WPF app with a "Grid Window". This window has no added XAML to it. I create a grid (columns and rows) then place a rectangle in each one all in C#.
This allows me to make a grid where I set the 'Stroke' and show locations on the grid when I set the 'Fill'.
The entire grid is set the same, in other words, if one part of the grid is red, the whole grid is red. Currently I set the grid by iterating through all of the rectangles and setting the 'Stroke' property. That works fine but seems very slow compared to most of the other operations. I would like to bind the stroke property to a variable in the C# (unless iterating is a reasonable way to handle it).
I have looked at quite a few questions here, but most want to use XAML. My code below is based off of Binding without XAML [WPF]. No errors, the grid just never shows up.
// put a rectangle in each square
for (int i = 0; i < x; i++) // for each column
{
for (int j = 0; j < y; j++) // for each row
{
// create a new rectangle with name, height, width, and starting color (transparent)
var rect = new Rectangle()
{
Name = $"rec{(i + 1).ToString("00")}{(j + 1).ToString("00")}", //column 5 row 2 -> rec0502
Height = squareSize,
Width = squareSize,
Fill = _ColorOff
};
// create the binding
var binder = new Binding
{
Source = _GridColor, // Brush that is updated on color change
Path = new PropertyPath("Stroke")
};
// apply the binding to the rectangle
rect.SetBinding(Rectangle.StrokeProperty, binder);
rect.DataContext = binder;
// place the rectangle
Grid.SetColumn(rect, i); // current column
Grid.SetRow(rect, (y - j - 1)); // same row but from the bottom (puts point 0,0 at bottom left)
// add the rectangle to the grid
grdBattleGrid.Children.Add(rect);
}
}
Even if iterating is fine, I'd still like to know what I'm doing wrong.
EDIT: The color name is chosen from a ComboBox on a separate window. This updates the user settings, which in turn throws an event my "Grid Window" is subscribed to. I convert the name to a SolidColorBrush before iterating though the rectangles.
The most simple solution would be not to have any Binding at all. Assign _GridColor to the Rectangle's Stroke. Whenever the Color property of (the assumed SolidColorBrush) _GridColor changes, it affects all Rectangles.
public SolidColorBrush _GridColor { get; } = new SolidColorBrush();
...
var rect = new Rectangle
{
Name = $"rec{(i + 1).ToString("00")}{(j + 1).ToString("00")}",
Height = squareSize,
Width = squareSize,
Fill = _ColorOff,
Stroke = _GridColor // here
};
Grid.SetColumn(rect, i);
Grid.SetRow(rect, (y - j - 1));
grdBattleGrid.Children.Add(rect);
Change the Rectangle Stroke by assigning a value to the Color property of the _GridColor Brush:
_GridColor.Color = Colors.Red;
You just need to set the DataContext one time for the Window, not for each Rectangle.
Is Binding your own view model class from INotifyPropertyChanged interface? Link to MS Docs

How to change the color of the DataPoint label based on the chart bar size?

I added a new chart control (System.Windows.Forms.DataVisualiation.Charting) with ChartType Bar.
As requirement the label text must be white and into the bar value. Therefore I set the BarLabelStyle=Right in the CustomProperties of the DataPoint objects and the LabelForeColor to White.
See the below images.
The label in the 2nd gray bar is correctly shown.
The first bar instead is too small and the white text is shown out on the right side but is not visible.
However, when the bar is too short, the label text is positioned outside the bar and the text cannot be seen using white color.
Is there a way to check when the label text is drawn outside the bar value so that I can change the color (e.g. black)?
Thanks.
Unfortunately MCChart has almost no capacities wrt to dynamic expressions.
To work around you can either..:
Code the ForeColor depending on the y-value your DataPoints has. Either right when you add them or in a function that loops over all points, whenever you call it.. - Depending on the Font, the axis range and the label text this could be some threshold number you have to determine.
Example:
int p = yourSeries.Points.AddXY(...);
yourSeries.Points[p].LabelForeColor = yourSeries.Points[p].YValues[0] < threshold ?
Color.Black : Color.White;
Or you can cheat a little ;-)
You can set the LabelBackColor to have the same color as the Series, i.e. the bar itself. Here is is how to do that:
To access the Series.Color we have to call:
chart.ApplyPaletteColors();
Now we can set
yourSeries.LabelForeColor = Color.White;
yourSeries.LabelBackColor = yourSeries.Color;
Example:
Update:
Since you can't use the cheat you will have to set the colors.
The challenge is to know just how much space each label's text needs compared to how much space the bars have. The former can be measured (TextRenderer.MeasureString()) and the latter can be extracted from the y-axis (Axis.ValueToPixelPosition()).
Here is a function to do that; it is a little more complicated than I had hoped for, mostly because it tries to be generic..
void LabelColors(Chart chart, ChartArea ca, Series s)
{
if (chart.Series.Count <= 0 || chart.Series[0].Points.Count <= 0) return;
Axis ay = ca.AxisY;
// get the maximum & minimum values
double maxyv = ay.Maximum;
if (maxyv == double.NaN) maxyv = s.Points.Max(v => v.YValues[0]);
double minyv = s.Points.Min(v => v.YValues[0]);
// get the pixel positions of the minimum
int y0x = (int)ay.ValueToPixelPosition(0);
for (int i = 0; i < s.Points.Count; i++)
{
DataPoint dp = s.Points[i];
// pixel position of the bar right
int vx = (int)ay.ValueToPixelPosition(dp.YValues[0]);
// now we knowe the bar's width
int barWidth = vx - y0x;
// find out what the label text actauly is
string t = dp.LabelFormat != "" ?
String.Format(dp.LabelFormat, dp.YValues[0]) : dp.YValues[0].ToString();
string text = dp.Label != "" ? dp.Label : t;
// measure the (formatted) text
SizeF rect = TextRenderer.MeasureText(text, dp.Font);
Console.WriteLine(text);
dp.LabelForeColor = barWidth < rect.Width ? Color.Black : Color.White;
}
}
I may have overcomplicated the way to get at the text that should show; you certainly can decide if you can simplify for your case.
Note: You must call this function..
whenever your data may have changed
only after the axes of the chart have finished their layout (!)
The former point is obvious, the latter isn't. It means that you can't call the function right after adding your points! Instead you must do it at some later place or else the axis function needed to get the bar size will not work.
MSDN says it can only happen in a PaintXXX event; I found that all mouse events also work and then some..
To be save I'll put it in the PostPaint event:
private void chart_PostPaint(object sender, ChartPaintEventArgs e)
{
LabelColors(chart, chart.ChartAreas[0], chart.Series[0]);
}

How to change colors of specific data points in a "series" of a chart?

I don't know if can make it clear otherwise, So here is the code:-
Series series2 = null;
for (int i = 0; i < 4; i++)
{
series2 = chart2.Series.Add(subjectnames[i]);
}
for (int i = 0; i < 4; i++)
{
series2.Points.Add(attemptper[i]);
series2.Points.Add(correctper[i]);
}
Now, I just want to display "attemptper" bars in different color than "correctper" bars. By default they are appearing in greyish-blue color. How do I get it done?
The charts appear all in bluish color. I want them to appear in different colors. I think I haven't added the data correctly to the chart for this to achieve?
You change the color on the series point(index) like this:
Chart1.Series[1].Points[0].Color = Color.Red
Getting the chart to repaint might also take some code, depending on what you're doing. For me, I wanted to animate my chart, building the data point (a column) dynamically as the program ran, showing the status of some work I was doing, which required this:
Chart1.Series.ResumeUpdates()
Chart1.Series[1].Points.Item[0].YValues = Double(1) {MyNewValue, 0}
Chart1.Series[1].Points[0].Color = Color.Red
Chart1.DataBind()
Chart1.Series.Invalidate()
Chart1.Series.SuspendUpdates()
I would suggest adding an extra series to your chart and changing the color set on that.

Is there a way to set the BackColor of Winforms ListView cells individually?

I want to color each list view cell's BackColor using a different color. Is this possible?
To change the colour of a cell's BackColor, you can do this:
listView1.Items[0].UseItemStyleForSubItems = false;
listView1.Items[0].SubItems[0].BackColor = Color.Green;
listView1.Items[0].SubItems[1].BackColor = Color.Orange;
listView1.Items[0].SubItems[2].BackColor = Color.Red;
// Change the 0 in Items[0] for whatever row you want,
// and the 0, 1 or 2 in SubItems[0] to whatever column you want.
The first line,
listView1.Items[0].UseItemStyleForSubItems = false;
Will make it so that the row of cells is not all coloured the same colour.
Here is a demo picture:
Hope this helps!
If you use this property, then it works:
myListView.Items[i].UseItemStyleForSubItems = false;

Categories