To whom this may concern:
I’ve been reading through the following posts:
https://www.scichart.com/questions/question/how-to-draw-oval-circle-annotation
https://www.scichart.com/questions/question/resizing-a-custom-annotation
Unfortunately, I’m no closer to generating a re-sizable oval ellipse: mainly because techman234’s response is all gibberish and I’ve no clue how to re-template a box annotation. I’ve observed your “create annotations dynamically” and “composite annotations.”
Could you give a more thorough tutorial on this? I would like to design a resizable custom annotation like I would a regular custom annotation without the AnchorPointAnnotations limitations.
Thanks kindly!
— Ari
EDIT: Found a resource but still need help
https://www.scichart.com/documentation/v4.x/webframe.html#The%20CustomAnnotation%20Type.html
So after doing some deeper digging, I came across this link that sufficiently explains how to make a box template. I was able to make an ellipse but the heights and widths are fixed. I can re-size the outer limits of the invisible “box” but the ellipse itself remains the same size.
I would like to be able to re-size and re-shape the ellipse along with the box. I would also, if possible, have a mechanism to rotate the ellipse to a certain angle.
Can you please advise?
Thanks!
- Ari Sagiv asked 7 years ago
- last edited 7 years ago
- You must login to post comments
I was going to suggest to you our Custom Annotation documentation page, which you found.
So what’s the issue? you simply need to set an Ellipse inside the Border and stretch it to fill. For instance:
<s:SciChartSurface.Annotations>
<s:BoxAnnotation X1="2" X2="8" Y1="2" Y2="8" Background="#33FFFFFF"
BorderBrush="#55FFFFFF" BorderThickness="3" Padding="5">
<s:BoxAnnotation.Template>
<ControlTemplate TargetType="s:BoxAnnotation">
<Border x:Name="PART_BoxAnnotationRoot"
Margin="{TemplateBinding Margin}">
<Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}"
Width="{Binding ElementName=PART_BoxAnnotationRoot, Path=ActualWidth"
Height="{Binding ElementName=PART_BoxAnnotationRoot, Path=ActualHeight" />
</Border>
</ControlTemplate>
</s:BoxAnnotation.Template>
</s:BoxAnnotation>
</s:SciChartSurface.Annotations>
Does that work?
- Andrew Burnett-Thompson answered 7 years ago
- Andrew — I’ve posted another issue as one of the answers.
- You must login to post comments
Andrew —
Thank you for you quick response. I’ve managed to get the ellipse to change its form as I liked, but I am having trouble accessing something from the Template in the CodeBehind.
My code is as follows:
<s:BoxAnnotation.Template>
<ControlTemplate TargetType="s:BoxAnnotation">
<Border x:Name="PART_BoxAnnotationRoot">
<Ellipse RenderTransformOrigin="0.5, 0.5" x:Name="Ellipse"
Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType=Border}}"
Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=Border}}"
Stroke="LightBlue" StrokeThickness="4">
<Ellipse.RenderTransform>
<RotateTransform Angle="-45" x:Name="Angle"/> <-- This is what I need access to in the codebehind -->
</Ellipse.RenderTransform>
</Ellipse>
</Border>
</ControlTemplate>
</s:BoxAnnotation.Template>
I am trying to access the “Angle” parameter from the “RotateTransform” markup using the Template.FindName() method, as follows:
var control = (Ellipse)this.Template.FindName("Ellipse", this);
but it is not retrieving the control. I’m not that experienced in XAML/code-behind. Could you please advise?
Thanks kindly! 🙂
— Ari
- Ari Sagiv answered 7 years ago
- last edited 7 years ago
- You can’t access something in a template from codebehind. It’s just not possible in WPF. What I suggest you do is create an attached property, set it on BoxAnnotation and bind from the RotateTransform Angle to BoxAnnotation via TemplateBinding..
- Andrew — I am doing my research and attempting a few solutions, but am having trouble doing this, can you please elaborate further?
- Never mind — it took me maybe 100-something tries but I think I’ve got it. I’ll post my code in the answer as soon as I’m sure it works.
- Andrew — I’ve posted an update to my answer, maybe this is something you’d want to look into? I can submit a ticket if needs be. — Ari
- You must login to post comments
So here’s what I’ve discovered. Using the following class for creating an attached property, bound to the BoxAnnotation class:
public class AngleDependency : DependencyObject
{
public static readonly DependencyProperty AngleProperty = DependencyProperty.RegisterAttached("Angle", typeof(object), typeof(BoxAnnotation), new PropertyMetadata(false));
public static void SetAngle(BoxAnnotation obj, double value)
{
obj.SetValue(AngleProperty, value.ToString());
}
public static double GetAngle(BoxAnnotation obj)
{
return double.Parse(obj.GetValue(AngleProperty).ToString());
}
}
And then using the following
<s:BoxAnnotation ... (all assembly declarations) ...
local:AngleDependency.Angle="0"> <!-- Attached Property -->
<s:BoxAnnotation.Template>
<ControlTemplate TargetType="s:BoxAnnotation">
<Border x:Name="PART_BoxAnnotationRoot">
<Ellipse RenderTransformOrigin="0.5, 0.5" x:Name="Ellipse"
Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType=Border}}"
Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=Border}}"
Stroke="LightBlue" StrokeThickness="4">
<Ellipse.RenderTransform>
<RotateTransform Angle="{Binding Path=(local:CovarianceEllipse.Angle), RelativeSource={RelativeSource TemplatedParent}}"/> <!-- More complex TemplateBinding to Angle, NOTE: CovarianceEllipse, not AngleDependency -->
</Ellipse.RenderTransform>
</Ellipse>
</Border>
</ControlTemplate>
</s:BoxAnnotation.Template>
</s:BoxAnnotation>
And then I run the following function:
private void showEllipse(object sender, System.Windows.RoutedEventArgs e)
{
var covarianceEllipse = new CovarianceEllipse
{
X1 = //some value
Y1 = //some value
X2 = //some value
Y2 = //some value
IsEditable = true
};
var item = AngleDependency.GetAngle(covarianceEllipse); // Just to see what the value set is, should be 0
AngleDependency.SetAngle(covarianceEllipse, -45);
processEquivalencyChart.Annotations.Add(covarianceEllipse);
}
And it seems to work, as shown in the attached image (You can see the ellipse is angled at 45 degrees instead of 0).
This is pretty bizzare, since I have to use “object” as the propertyType even though it’s a double that I’m working with, and the “TemplateBinding” binds to a “CovarianceEllipse.Angle” instead of an “AngleDependency.Angle” as in the primary markup. (Changing either brings an exception.)
I know it works, I just want to make sure this is the right way to do it. I would appreciate any comments or suggestions.
— Ari
EDIT: — So while this works, it’s very tricky to transform and it’s not static (meaning it changes shape as I try to zoom). Sometimes only a partial ellipse will appear, and everything outside the bounds of the BoxAnnotation disappears. I’ve attached some more figures to show.
6.png shows the ellipses after some transformation. You can see the top right (larger) ellipse is cut off. The bottom left (smaller) ellipse is still intact. Zooming in on that ellipse, you can see the shape changes in 7.png (some points are now outside the ellipse) and it’s also only partial.
Maybe it’s time to make a new “EllipseAnnotation?” 🙂
- Ari Sagiv answered 7 years ago
- last edited 7 years ago
- It is exactly the right way to do it, well done!! Except … I think you should try using LayoutTransform not RenderTransform. There is a good article here on the difference http://blog.scottlogic.com/2008/12/19/layouttransform-vs-rendertransform-whats-the-difference.html
- Andrew — Actually LayoutTransform doesn’t quite work.. 8.png shows an ellipse with the width and height set as you specified in your second answer (relative to the Border boundaries), and it gets cut off. Changing CenterX and CenterY as part of the RotateTransform function doesn’t really do anything. Another issue is shown in 9, 10, and 11 png, which is when I resize the BoxAnnotation boundaries after removing the width and height constraints. The angle in this case is 35 degrees, as 45 will always get you a circle no matter how the ellipse is shaped. When I shrink the size of the box, the size of the entirety of the ellipse changes, until it becomes a perfect square, where the ellipse becomes a circle. When shrinking the width even lower, the diretion of the ellipse changes. Is there some way that I can just keep the ellipse inscribed by the boundaries of the BoxAnnotation? Thanks kindly! — Ari
- Andrew — I’ve attached a schematic of what I’m trying to achieve with creating an ellipse (12.png). Hopefully it makes some sense. I would, of course, like to be able to adjust the aspect ratio (long radius/short radius ratio) of the ellipse. These are primarly for showing the covariance of the scattered data. — Ari
- Andrew — I figured out a way of doing this without using annotation: I use the FastMountainRenderableSeries after calculating the necessary parameters. It’s not an annotation, but at least it’s static works well when zooming. Unfortunately it involves setting the “AcceptsUnsortedData” to true, but there are only 100 data points in the ellipse, hardly anything that makes a major difference. If you’d like any more information. I’m happy to share. — Ari
- You must login to post comments
Please login first to submit.