I have some code to apply DropShadowBitmapEffect to UserControl.
Visual Studio says that this.BitmapEffect is deprecated and we have to use Effects.
How it should be done then?
DropShadowBitmapEffect myDropShadowEffect = new DropShadowBitmapEffect();
myDropShadowEffect.Color = GetShadowColorValue();
myDropShadowEffect.Direction = 250;
// Set the depth of the shadow being cast.
myDropShadowEffect.ShadowDepth = 0;
// Set the shadow softness to the maximum (range of 0-1).
myDropShadowEffect.Softness = 1;
// Set the shadow opacity to half opaque or in other words - half transparent.
// The range is 0-1.
myDropShadowEffect.Opacity = 0.7;
// Apply the bitmap effect to the Button.
this.BitmapEffect = myDropShadowEffect; // BitmapEffect is deprecated
DropShadowEffect myDropShadowEffect = new DropShadowEffect();
myDropShadowEffect.Color = GetShadowColorValue();
myDropShadowEffect.Direction = 250;
// Set the depth of the shadow being cast.
myDropShadowEffect.ShadowDepth = 0;
// Set the shadow softness to the maximum (range of 0-1).
// myDropShadowEffect.Softness = 1;
// Set the shadow opacity to half opaque or in other words - half transparent.
// The range is 0-1.
myDropShadowEffect.Opacity = 0.7;
// Apply the effect to the Button.
this.Effect = myDropShadowEffect;
I'm not sure what is the equivalent of Softness... you can try to adjust the BlurRadius value
Related
Is it possible(Without looping through all texturecoordinates) to set them as 0 as default?
I am creating a linear gradient ImageBrush
var colorBitmap = GetColorsBitmap(gradient.ToList()); // Create Colors from gray to my selected color
ImageBrush ib = new ImageBrush(colorBitmap)
{
ViewportUnits = BrushMappingMode.Absolute,
Viewport = new Rect(0, 0, 1, 1) // Matches the pixels in the bitmap.
};
myModel.Material = new DiffuseMaterial(ib);
Then depending on a condition I customize some of the Texturecoordinates like this, where colorvalue is the distance from an object:
var mesh = (MeshGeometry3D) myModel.Geometry;
//In a loop, depending on the distance I set a colorValue
mesh.TextureCoordinates[count] = new Point(colorValue, 0);
I want every texturecoordinate to default to a Point(0,0) but if I have to loop through all 1.2 million of them takes too much time. So is there a way to setup my ImageBrush so that they default to 0,0 or something similiar?
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
By default, the angles on the polar chart go from 0 to 360 in a clockwise direction but I want them to go counter clockwise (anticlockwise)
chart.ChartAreas[0].AxisX.Title = "Elevation";
chart.ChartAreas[0].AxisY.Title = "Power(dBm)";
chart.ChartAreas[0].BackColor = System.Drawing.Color.FromArgb(211, 223, 240);
chart.ChartAreas[0].BorderColor = System.Drawing.Color.FromArgb(26, 59, 105);
chart.ChartAreas[0].AxisY.IsStartedFromZero = false;
chart.PrePaint += new EventHandler<ChartPaintEventArgs>(chart_prePaint);
I've tried changing the labels per some example code I found like this:
CustomLabelsCollection labels = chart.ChartAreas[0].AxisX.CustomLabels;
if (labels == null) return;
for (int i = 0; i < labels.Count - 1; i++)
{
if (labels[0].Text == "360") break;
labels[i].Text = (360 - int.Parse(labels[i].Text)).ToString();
labels[i].ToolTip = "Angle in Degrees";
}
The code changes the labels in the object but not on the graph. And every time the event is fired and we come back into this event handler, the labels have been reset to the way it was originally.And the tooltips have been reset.
To add to the confusion, I'm not sure why the CustomLabels object is populated in the first place - I didn't do it.
Any idea why the changes are having no effect?
Thanks in advance!
If you want something like this:..
..CustomLabels are indeed a way to achieve it. I couldn't find a way make the axis reverse itself..
Here is the C# code I used:
Axis ay = chart.ChartAreas[0].AxisY;
ay.LabelStyle.Enabled = false;
Axis ax = chart.ChartAreas[0].AxisX;
ax.CustomLabels.Clear();
int step = (int)ax.Interval;
if (step == 0) step = 30;
for (int i = 0; i < 360; i+=step)
{
int a = 360 - i; // the angle to target
var cl = new CustomLabel();
cl.Text = a + "°";
cl.FromPosition = a + 0.01; // create a small..
cl.ToPosition = a - 0.01; // ..space to place the label !
ax.CustomLabels.Add(cl);
}
Note that only the Labels are reversed, not the values!
To start at 0 simply change the loop condition to <= and check for i>0 before creating the labels!
If you didn't set an Interval I use a default interval of 30; change as needed!
The CustomLabels collection by default is created, so it isn't null but it is empty (Count==0). If you didn't create any, then there are none and the original AxisLabels are showing. (Only one type be shown!)
Unless you have a really good reason, like very dynamic data, you should not add of modify anything in a xxxPaint event! They may be called quite often and these event are really just for drawing. ((And sometimes for measuring))
I have a Winforms chart in which I have temperature readings arriving and displaying every second. I like the way the chart works automatically handling the display of the values, but I want to change one simple thing.
I want to increase the minimum displayed y axis range, so it displays a range of 20. At the moment it only displays around 5. I have tried a few things:
//(when new data arrives...)
//Does not work, I think because by default, Size is always NaN?
if (chart1.ChartAreas[0].AxisY.ScaleView.Size < 20)
{
chart1.ChartAreas[0].AxisY.ScaleView.Size = 20;
}
None of these work either:
chart1.ChartAreas[0].AxisY.ScaleView.SmallScrollMinSize = 20;
chart1.ChartAreas[0].AxisY.ScaleView.SmallScrollSize = 20;
chart1.ChartAreas[0].AxisY.ScaleView.MinSize = 20;
chart1.ChartAreas[0].AxisY.Minimum //doesn't seem to have any effect
chart1.ChartAreas[0].AxisY.Maximum //doesn't seem to have any effect
I'm sure I've missed something simple. I hope I have anyway.
The 'minimum display range' is not something built-in in the MSChart control.
But you can easily fake it:
Add a dummy Series which contains only two points to make sure the display range will not go below the range of their y-values..:
int rangeMin = -10;
int rangeMax = 20;
sDummy = chart.Series.Add("dummy");
sDummy.Color = Color.Transparent;
sDummy.IsVisibleInLegend = false;
sDummy.ChartType = SeriesChartType.Point;
sDummy.Points.AddXY(0, rangeMin + 1);
sDummy.Points.AddXY(0, rangeMax - 1);
Style your y-axis as you like:
Axis ay = chart.ChartAreas[0].AxisY;
ay.MajorGrid.Interval = 5;
And add one or more data Series:
sData = chart.Series.Add("data");
sData.LegendText = "Temperature";
sData.ChartType = SeriesChartType.Line;
Now as you add data points with a larger range of values the y-axis will grow its display range to accommodate them. And if you remove the larger points it will shrink back, but not below the range needed for the dummy series..:
Note that since the Chart automatically adds some slack I reduce the range on both sides by 1; with other Intervals etc other numbers are needed..
The code to remove the larger values, btw:
var toRemove = sData.Points.Cast<DataPoint>()
.Where(x => x.YValues[0] >= rangeMax).ToList();
foreach (var dp in toRemove) sData.Points.Remove(dp);
I have a chart control (from System.Windows.Forms.DataVisualization) with two chart areas. ChartArea2 is aligned to ChartArea1 as follows:
ChartArea2.AlignWithChartArea = "ChartArea1";
ChartArea2.AlignmentOrientation = AreaAlignmentOrientations.Vertical;
ChartArea2.AlignmentStyle = AreaAlignmentStyles.All;
This works well except the X Axes are not aligned, despite being included in the AlignmentStyle. Instead, their minimum, maximum, interval, etc remain independent and are set according to the datapoints.
I need the X Axes to be identical, i.e. min, max, interval, etc. I can set these properties in code to force them to be identical. However, as soon as I zoom into ChartArea1, then the X Axes become misaligned again.
Is there a simple way for the X Axes to mirror each other regardless of the zoom level?
Well, they actually are aligned , i.e. sit at the same position regardless of their labels but they don't have the same range.
You don't see the alignment of the X-Axes when the sit vertically but look at the Y-Axes: They have different Font sizes but sit at the same horizontal position!
If you want to show the same range you need to set the range, as you wrote, by setting the Minimum & Maximum from the default NaN (which here means Automatic) to some values.
And when you zoom one the other will zoom in parallel automatically as long as AreaAlignmentStyles.AxesView or AreaAlignmentStyles.All are selected.
So what you need is the combination of a non-automatic, explicit range (for the unzoomed state) and and a suitable AreaAlignmentStyle (for the zoomed state.)
Note that the AlignmentStyle needs to be made only for one of the two ChartAreas. But the Minimum/Maximum values need to be set for both:
ChartArea CA1 = chart1.ChartAreas[0];
ChartArea CA2 = chart1.ChartAreas.Add("ChartArea2");
// 2nd CA aligns to the 1st one:
CA2.AlignWithChartArea = "ChartArea1";
CA2.AlignmentOrientation = AreaAlignmentOrientations.Vertical;
CA2.AlignmentStyle = AreaAlignmentStyles.All;
// both have the same range:
CA1.AxisX.Maximum = 30;
CA2.AxisX.Maximum = 30;
CA1.AxisX.Minimum = 0;
CA2.AxisX.Minimum = 0;
// both are interactively zoomable:
CA1.AxisX.ScaleView.Zoomable = true;
CA1.AxisX.ScrollBar.Enabled = true;
CA1.CursorX.IsUserSelectionEnabled = true;
CA2.AxisX.ScaleView.Zoomable = true;
CA2.AxisX.ScrollBar.Enabled = true;
CA2.CursorX.IsUserSelectionEnabled = true;
In a zoomed state both ChartAreas still show the same range and have the same ScaleView.ViewMinimum / ScaleView.ViewMaximum:
Code to test the ScaleView values:
private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
{
AxisScaleView ASV1X = chart1.ChartAreas[0].AxisX.ScaleView;
AxisScaleView ASV2X = chart1.ChartAreas[1].AxisX.ScaleView;
label1.Text = "ScaleViews Min/Max: " + ASV1X.ViewMinimum + " - " + ASV1X.ViewMaximum +
" | " + ASV2X.ViewMinimum + " - " + ASV2X.ViewMaximum ;
}
Note that to keep not only the value ranges aligned but also the visual display of the Axes you need to use the AlignmentStyle = AreaAlignmentStyles.All;, not just AxisView or else great differences in the values' formatting results or in the number of points to display can move the Y-Axis and make the X-Axes look misaligned!
Setting ChartArea.AxisX.IsMarginVisible = false; will solve the problem