|
|
Comments and Discussions
|
|
 |

|
Thank you for your useful and nice Control
|
|
|
|

|
Very nice circular gauge article.
Just because the code works, it doesn't mean that it is good code.
|
|
|
|

|
I implement this control in my project.
the designer mode display the gauge but when i execute the code i have the XamlParseException.
I don't inderstand the wrong
thank you again for your solution. I hope to have an anwser
thank you
|
|
|
|

|
Hi, thank you very much for this nice Control!
I have a problem to set a Start Value for the Pointer. When my CurrentValue for the Pointer is at Application startup at 1000 the Pointer shows to 0 because the Storyboard isnt started.
Does anyone have an Idea how to fix this?
|
|
|
|

|
please help ,
how binding with Min/Max
thx
|
|
|
|

|
I wrote a method to refresh the scale at runtime.
public void RefreshScale()
{
rootGrid = GetTemplateChild("LayoutRoot") as Grid;
for (int i = rootGrid.Children.Count - 1; i >= 0 ; i-- )
{
TextBlock textblock = rootGrid.Children[i] as TextBlock;
if (textblock != null) {
if(textblock.Text != this.DialText) rootGrid.Children.Remove(textblock);
continue;
}
Rectangle rectangle = rootGrid.Children[i] as Rectangle;
if (rectangle != null) {
rootGrid.Children.Remove(rectangle);
continue;
}
}
this.OnApplyTemplate();
}
|
|
|
|

|
There is a bug in this code when the drawing the optimal range if the difference between MinValue and MaxValue is less than 1.0. So, for example, if you need a gauge where the MinValue is 0.05 and the MaxValue is 0.10, and your optimal range is 0.075 to 0.080, it will not draw your optimal range correctly.
The fix is in the DrawRangeIndicator function, in that it needs to scale some of the calculations in this case. I have posted an updated function below.
private void DrawRangeIndicator()
{
Double rangediff = MaxValue - MinValue;
Double realworldunit = (ScaleSweepAngle / rangediff);
Double optimalStartAngle;
Double optimalEndAngle;
double db;
double tmprangediff = rangediff;
for (int i = 1; i <= ScaleValuePrecision; i++)
{
if (tmprangediff < 1)
{
tmprangediff *= 10;
realworldunit /= 10;
}
else
{
break;
}
}
if (OptimalRangeStartValue < 0)
{
db = MinValue + Math.Abs(OptimalRangeStartValue);
optimalStartAngle = ((double)(Math.Abs(db * realworldunit)));
}
else
{
db = OptimalRangeStartValue - MinValue;
optimalStartAngle = ((double)(db * realworldunit));
}
if (OptimalRangeEndValue < 0)
{
db = MinValue + Math.Abs(OptimalRangeEndValue);
optimalEndAngle = ((double)(Math.Abs(db * realworldunit)));
}
else
{
db = OptimalRangeEndValue - MinValue;
optimalEndAngle = ((double)(db * realworldunit));
}
tmprangediff = rangediff;
for (int i = 1; i <= ScaleValuePrecision; i++)
{
if (tmprangediff < 1)
{
tmprangediff *= 10;
optimalStartAngle *= 10;
optimalEndAngle *= 10;
}
else
{
break;
}
}
Double optimalStartAngleFromStart = (ScaleStartAngle + optimalStartAngle);
Double optimalEndAngleFromStart = (ScaleStartAngle + optimalEndAngle);
arcradius1 = (RangeIndicatorRadius + RangeIndicatorThickness);
arcradius2 = RangeIndicatorRadius;
double endAngle = ScaleStartAngle + ScaleSweepAngle;
Point A = GetCircumferencePoint(ScaleStartAngle, arcradius1);
Point B = GetCircumferencePoint(ScaleStartAngle, arcradius2);
Point C = GetCircumferencePoint(optimalStartAngleFromStart, arcradius2);
Point D = GetCircumferencePoint(optimalStartAngleFromStart, arcradius1);
bool isReflexAngle = Math.Abs(optimalStartAngleFromStart - ScaleStartAngle) > 180.0;
DrawSegment(A, B, C, D, isReflexAngle, BelowOptimalRangeColor);
Point A1 = GetCircumferencePoint(optimalStartAngleFromStart, arcradius1);
Point B1 = GetCircumferencePoint(optimalStartAngleFromStart, arcradius2);
Point C1 = GetCircumferencePoint(optimalEndAngleFromStart, arcradius2);
Point D1 = GetCircumferencePoint(optimalEndAngleFromStart, arcradius1);
bool isReflexAngle1 = Math.Abs(optimalEndAngleFromStart - optimalStartAngleFromStart) > 180.0;
DrawSegment(A1, B1, C1, D1, isReflexAngle1, OptimalRangeColor);
Point A2 = GetCircumferencePoint(optimalEndAngleFromStart, arcradius1);
Point B2 = GetCircumferencePoint(optimalEndAngleFromStart, arcradius2);
Point C2 = GetCircumferencePoint(endAngle, arcradius2);
Point D2 = GetCircumferencePoint(endAngle, arcradius1);
bool isReflexAngle2 = Math.Abs(endAngle - optimalEndAngleFromStart) > 180.0;
DrawSegment(A2, B2, C2, D2, isReflexAngle2, AboveOptimalRangeColor);
}
|
|
|
|

|
Dim NewGrid1 As New Grid
NewGrid1.Name = "NewGrid1"
Dim NewKpi As New CircularGauge.CircularGaugeControl
With (NewKpi)
.Name = "NewKpi1"
.Radius = 150
.ScaleRadius = 110
.ScaleStartAngle = 120
.ScaleSweepAngle = 300
.PointerLength = 85
.PointerCapRadius = 35
.MinValue = 0
.MaxValue = 1000
.MajorDivisionsCount = 10
.MinorDivisionsCount = 5
.CurrentValue = 0
.ImageSize = New System.Windows.Size(40, 50)
.RangeIndicatorThickness = 8
.RangeIndicatorRadius = 120
.RangeIndicatorLightRadius = 10
.RangeIndicatorLightOffset = 80
.ScaleLabelRadius = 90
.ScaleLabelSize = New System.Windows.Size(40, 20)
.ScaleLabelFontSize = "10"
.ScaleLabelForeground = myGauge1.ScaleLabelForeground
.MajorTickSize = New System.Windows.Size(10, 3)
.MinorTickSize = New System.Windows.Size(3, 1)
.MajorTickColor = myGauge1.MajorTickColor
.MinorTickColor = myGauge1.MinorTickColor
.ImageOffset = "-50"
.GaugeBackgroundColor = myGauge1.GaugeBackgroundColor
.PointerThickness = "16"
.OptimalRangeStartValue = "300"
.OptimalRangeEndValue = "700"
.DialTextOffset = "40"
.DialText = "TextHere"
.DialTextColor = myGauge1.DialTextColor
End With
Dim Fuente1 As New FuenteDatosGauge
NewKpi.DataContext = Fuente1
Dim Bind As New Binding
Bind.Source = Fuente1
Bind.Path = New PropertyPath("ValorActual1")
NewKpi.SetBinding(CircularGauge.CircularGaugeControl.CurrentValueProperty, Bind)
Dim FinalValue As Decimal
FinalValue = Math.Round(250, 2)
Fuente1.ValorActual1 = FinalValue
NewKpi.DialText = FinalValue
|
|
|
|

|
dim MyGauge As CircularGauge.CircularGaugeControldim
and so on...
|
|
|
|
|

|
I'm trying to get this to work in Visual Studio 2010 with silverlight 4, I'm sure this "should" work, just would like a confirmation...
|
|
|
|

|
Hi
Range is covering whole circle for some particular Max and Min Value.
If i set Max = 20 and Min = -200 and want to draw range from -200 to 20 (using Arc) then angle is dropped instead covering the circle.
|
|
|
|

|
Hi EvelynT,
I am using your gauge control, a nice application. In my project I want to split a gauge into three parts (one part to show gas left over, one for coolant, one for temperature). Each part should show the indicator by color change with out any pointer. Would you please guide me for this task.
Thanks
Reddy
|
|
|
|

|
Hi
Im using and testing this gauge control and it is pretty nice. How must I do it, when I want to change MaxValue, OptimalRangeStartValue and OptimalRangeEndValue on Runtime?
If I only change the properties nothing happens.
Thanks for the help!
|
|
|
|

|
1、 As described by GaborTorok, 2:02 10 Feb '10
The DrawRangeIndicator() function, that works for me is included below.
//double db;
////Checking whether the OptimalRangeStartvalue is -ve
//if (OptimalRangeStartValue < 0)
//{
// db = MinValue + Math.Abs(OptimalRangeStartValue);
// optimalStartAngle = ((double)(Math.Abs(db * realworldunit)));
//}
//else
//{
// db = Math.Abs(MinValue) + OptimalRangeStartValue;
// optimalStartAngle = ((double)(db * realworldunit));
//}
optimalStartAngle = realworldunit * (OptimalRangeStartValue - MinValue);
////Checking whether the OptimalRangeEndvalue is -ve
//if (OptimalRangeEndValue < 0)
//{
// db = MinValue + Math.Abs(OptimalRangeEndValue);
// optimalEndAngle = ((double)(Math.Abs(db * realworldunit)));
//}
//else
//{
// db = Math.Abs(MinValue) + OptimalRangeEndValue;
// optimalEndAngle = ((double)(db * realworldunit));
//}
// calculating the angle for optimal Start value
optimalEndAngle = realworldunit * (OptimalRangeEndValue - MinValue);
2、The OnCurrentValueChanged() Function ,should be modified as below:
if (pointer != null)
{
//double db1 = 0;
Double oldcurr_realworldunit = 0;
Double newcurr_realworldunit = 0;
Double realworldunit = (ScaleSweepAngle / (MaxValue - MinValue));
//Resetting the old value to min value the very first time.
if (oldValue == 0 && !isInitialValueSet)
{
oldValue = MinValue;
isInitialValueSet = true;
}
//if (oldValue < 0)
//{
// db1 = MinValue + Math.Abs(oldValue);
// oldcurr_realworldunit = ((double)(Math.Abs(db1 * realworldunit)));
//}
//else
//{
// db1 = Math.Abs(MinValue) + oldValue;
// oldcurr_realworldunit = ((double)(db1 * realworldunit));
//}
//Add one line
oldcurr_realworldunit = ((double)(realworldunit) *(oldValue-MinValue));
//if (newValue < 0)
//{
// db1 = MinValue + Math.Abs(newValue);
// newcurr_realworldunit = ((double)(Math.Abs(db1 * realworldunit)));
//}
//else
//{
// db1 = Math.Abs(MinValue) + newValue;
// newcurr_realworldunit = ((double)(db1 * realworldunit));
//}
//Add one line
newcurr_realworldunit = ((double)(realworldunit)*(newValue-MinValue));
Double oldcurrentvalueAngle = (ScaleStartAngle + oldcurr_realworldunit);
Double newcurrentvalueAngle = (ScaleStartAngle + newcurr_realworldunit);
//Animate the pointer from the old value to the new value
AnimatePointer(oldcurrentvalueAngle, newcurrentvalueAngle);
}
|
|
|
|

|
thank you for sharing your code. i am also trying to write some custom controls for one of my projects. Your code will help me a lot in finding the answer to some questions i have.
|
|
|
|

|
I have added a property ThickenessExsternalEllipse to control the thickness of the gauge border.
In generic.xaml I changed the StrokeThickess property
<Ellipse x:Name="OuterFrame" StrokeThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ThickenessExsternalEllipse}"
Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Radius, Converter={StaticResource radiusToDiameterConverter}}"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Radius, Converter={StaticResource radiusToDiameterConverter}}"
...
In CircularGauceControl.cs I added the DependecyProperty ThickenessExsternalEllipseProperty
public static readonly DependencyProperty ThickenessExsternalEllipseProperty =
DependencyProperty.Register("ThickenessExsternalEllipse", typeof(int), typeof(CircularGaugeControl), null);
...
public int ThickenessExsternalEllipse
{
get
{
return (int)GetValue(ThickenessExsternalEllipseProperty);
}
set
{
SetValue(ThickenessExsternalEllipseProperty, value);
}
}
Enrico Oliva
|
|
|
|

|
Is it true it is not possible to change the properties ScaleRadius, ScaleLabelRadius, RangeIndicatorRadius while running the application.
|
|
|
|

|
Thanks a lot for this uber cool gauge control. You're the MAN!
|
|
|
|

|
Hi,
I use this control in Silverlight but I've tried to bind the MaxValue (by the MVVM pattern) but it doesn't work. How do it ?
|
|
|
|

|
Solves a display problem for me quickly and easily--elegant and flexible gadget.
modified on Sunday, August 29, 2010 1:16 PM
|
|
|
|

|
Evelyn,
First - I must say that this is an AWESOME control. Congrats for this. Now, on to my problem....
I am trying to use this as a WPF control using just the .dll. I need to use this outside of Visual Studio. As a test in Visual Studio, I attempted to use the WPF control by referencing the dll in a new VS C# project (works fine), adding the control to the toolkit (works fine), and then dragging and dropping the control onto the form (boom!!). I get a dialog box complaining about the font size of "0".
What am I missing?? Have you heard of this issue before?
Thank in advance for your help, and for a great control!!
Jamie
|
|
|
|

|
For some reason I am unable to find the .dll in order to reference it...can anybody help? Where do I download it from?
|
|
|
|

|
I have a requirement to make this dial as hyperlink , so if user clicks on this dial needs to navigate to other page.Plz help me.
|
|
|
|

|
I think the live demo link needs updating? Possibly linking to the SL3 runtime? Controls look nice, will give them a run.
Best wishes
Jerry
|
|
|
|

|
Binding to CurrentValue (or just setting any value to it) does not work in my application. Upon debugging, I found out that the needle does not move because the pointer object is null when the code reaches AnimatePointer:
void AnimatePointer(double oldcurrentvalueAngle, double newcurrentvalueAngle)
{
if (pointer != null)
Also, I found out that OnApplyTemplate (where the pointer object is created) only fires after the AnimatePointer method is called (which explains why pointer was null?).
Other than that, the control looks very nice!
maybe one other thing to improve is to use default values for the dependencyproperties, so the control does not crash if you do not provide them and you do not have to specify so much in xaml.
|
|
|
|

|
Hi, fisrt very good work, very nice result!
i would like to know how to rezie a gauge?
|
|
|
|

|
Hello, contratulations for this sample.
With below scenario the RangeIndicator Bellow Optimal and Above Optimal lines are drawn wrong.
<gauge:CircularGaugeControl x:Name="myGauge2" Grid.Column="1" Grid.Row="0"
Radius="150"
ScaleRadius="100"
ScaleStartAngle="140"
ScaleSweepAngle="270"
PointerLength="90"
PointerCapRadius="35"
MinValue="30"
MaxValue="35"
MajorDivisionsCount="10"
MinorDivisionsCount="5"
OptimalRangeEndValue="32"
OptimalRangeStartValue="31"
CurrentValue="{Binding Score}"
ImageSource="windowslogo.png"
ImageSize="40,50"
RangeIndicatorThickness="9"
RangeIndicatorRadius="80"
RangeIndicatorLightRadius="10"
RangeIndicatorLightOffset="80"
ScaleLabelRadius="115"
ScaleLabelSize="40,20"
ScaleLabelFontSize="10"
ScaleLabelForeground="White"
MajorTickSize="10,3"
MinorTickSize="3,1"
MajorTickColor="White"
MinorTickColor="LightGray"
ImageOffset="-50"
GaugeBackgroundColor="CornflowerBlue"
PointerThickness ="5"
DialTextOffset="40"
DialText="Aqua Blue"
DialTextColor="DarkBlue"
/>
Here is the result image: http://dl.dropbox.com/u/3763901/gaugeError.PNG[^]
Any way how to solve this?
|
|
|
|

|
I want to modify the Min, Max and optimal range values at runtime using bindings; aim is to allow user to modify these values. Is it possible to do this? Has anyone tried doing this?
Any ideas, suggestions, comments...
|
|
|
|

|
Hi,
Has anyone else found this to consume huge amounts of CPU time ?? If so is there a way to fix it ?
I have this deployed on a test site and when the gauge is displayed, my CPU cycles goes to 100%. If I remove this control - I'm back down at a couple of % again.
Regards
Graham
|
|
|
|

|
This is really great, exactly what i was looking for.
I noticed a very small bug for the DialTextFontSize:
DependencyProperty.Register("DialTextFontSize", typeof(int)...
Should be a double:
DependencyProperty.Register("DialTextFontSize", typeof(double)...
(Also change the public property int DialTextFontSize to a double)
Thanks for this great control.
Greetings,
Patrick
|
|
|
|

|
Very good!! Thanks a lot to share with us!!
Gustavo Malheiros.
|
|
|
|

|
Hi,
The control is really excellent, but I need to apply different themes during run time. Is it possible?
Thanks in advance,
Matías
|
|
|
|

|
Hi, thanks for this very cool control, I'm going to give it a try for my dashboard project.
cheers
sushibite
|
|
|
|

|
Hi EvelynT,
I found your control very use full but I would like add it from code behind but unable to do so.
I am getting emtpy gage with no MinValue or MaxValue and needle is always set to minValue.
here is my code.
this.myStackPanel.Children.Add(new CircularGaugeControl()
{
Radius = Convert.ToDouble(150),
ScaleRadius = Convert.ToDouble(110),
ScaleStartAngle = Convert.ToDouble(120),
ScaleSweepAngle = Convert.ToDouble(300),
PointerLength = Convert.ToDouble(85),
PointerCapRadius = Convert.ToDouble(35),
MinValue = Convert.ToDouble(0),
MaxValue = Convert.ToDouble(1000),
MajorDivisionsCount = Convert.ToDouble(10),
MinorDivisionsCount = Convert.ToDouble(5),
CurrentValue = Convert.ToDouble(50),
RangeIndicatorThickness = Convert.ToDouble(8),
RangeIndicatorRadius = Convert.ToDouble(120),
RangeIndicatorLightRadius = Convert.ToDouble(10),
RangeIndicatorLightOffset = Convert.ToDouble(80),
ScaleLabelRadius = Convert.ToDouble(90),
ScaleLabelSize = new Size(40, 20),
ScaleLabelFontSize = Convert.ToDouble(10),
ScaleLabelForeground = Colors.LightGray,
MajorTickSize = new Size(10, 3),
MinorTickSize = new Size(3, 1),
MajorTickColor = Colors.LightGray,
MinorTickColor = Colors.LightGray,
ImageOffset = Convert.ToDouble(-50),
GaugeBackgroundColor = Colors.LightGray,
PointerThickness = Convert.ToDouble(16),
OptimalRangeStartValue = Convert.ToDouble(300),
OptimalRangeEndValue = Convert.ToDouble(700),
DialTextOffset = Convert.ToDouble(40),
DialText = "Breach",
DialTextColor = Colors.Black
});
|
|
|
|

|
Thanks for the Handy control.
I'm using the control as WPF custom control in Excel task pane (Created a WPF user control, and embed it in Winform user control using ElementHost Class, that finally added to the excel taskpane controls).
However, I still can't figred out how to use the data binding of to control to get specific cell value in excel.
Any help will be appriciated
|
|
|
|

|
Hi,
very useful content, I tried by loading the same in the C# code, it display the gauge but there is no needle movement, I Dont know how to set the CurrentValue in the Code, Can you please tell me how to do that?
thanks,
|
|
|
|

|
Very nice work...enjoyable and functional!
|
|
|
|

|
You did fantastic job. This is a very nice and handy control. Keep sharing some good stuffs with us.
Maulik Patel
|
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
An article on creating a circular gauge custom control for Silverlight 3.
| Type | Article |
| Licence | BSD |
| First Posted | 21 Jul 2009 |
| Views | 137,312 |
| Downloads | 8,157 |
| Bookmarked | 125 times |
|
|