Settings TranslateX or Canvas.SetLeft Property programmatically in Silverlight - wpf

So Here is the Problem, I am trying to get that circle to align on the number. When I do that in blend it shows me I have a Left (23), I try to do that programmaticly Canvas.SetLeft(thePanel,23) it overshoots. Better yet, if anyone knows of a control like this in silverlight let me know. What this does is when the user clicks on a number the green circle is suppose to go to that number so it looks like the user has selected it.

On your Circle object you have to set the Radius of the circle and the TranslateTransform attribute. Lets say your Circle has a radius of 15:
private const double Radious = 15.0;
private double _x = Radious;
private double _y = Radious;
private TranslateTransform _translation = new TranslateTransform();
and properties to handle the Circle's X and Y coordinates,
public double X
{
get { return this._x; }
set
{
this._x = value;
_translation.X = this._x - Radious;
}
}
public double Y
{
get { return this._y; }
set
{
this._y = value;
_translation.Y = this._y - Radious;
}
}
and in Silverlight you can get where the user has clicked on a Canvas, setting this code on the Click Event of the panel, and set the center of the circle to where the user has clicked:
//Get the points where it was clicked
Point clickPoint = e.GetPosition(Canvas);
MyCircle.X = clickPoint.X;
MyCircle.Y = clickPoint.Y;
Now, if you want them to always fall in fixed positions, you can set conditions that, if a user clicks around a number, then set the center of the circle to the center of the number, or just change the X value of your circle to move to the desired position.

Related

Binding of relative position of a control

I have a draggable user control within another user control indicating the distance of a vessel from another vessel. The placement of the object is bound to X, Y values in the back end. If the user loads a "mission", the location of this draggable object should snap to the position based on the X and Y values. Additionally, if the user drags the boat but then cancels, the position of the boat should snap back to its original position before it was dragged.
I find that if I bind to the Margin field, the margin is set correctly on the control but the draggable object stays in the same place, as if it is at 0,0,0,0 with the updated values (I can force it to move by editing the xaml and proving that any margin changes act as if the new values are 0,0,0,0:
public Thickness DaughtershipMargin
{
get { return _daughtershipMargin; }
set
{
_daughtershipMargin = value;
OnPropertyChanged();
}
}
I have also experimented with using a Canvas instead with similar results.
When initially dragging, the position is based on the relative position of the control based on a parent control - so it needs I need to do something similar
private void MouseDragElementBehavior_Dragging(object sender, MouseEventArgs e)
{
double x = System.Math.Round((e.GetPosition(colabdragObjectGrid).X - 280), 3);
double y = System.Math.Round((-1 * (e.GetPosition(colabdragObjectGrid).Y - 280)), 3);
if (x >= _minFollowDistance && x <= _maxFollowDistance && y >= _minFollowDistance && y <= _maxFollowDistance)
{
_parent.ProcessDragEvent(x.ToString(), y.ToString());
}
}
<Grid x:Name="colabdragObjectGrid" Margin="0,-10,0,0" Height="575" Width="575">
<local:colabdrag x:Name="colabdragObject" Height="100" Width="100" RenderTransformOrigin="0.5,0.5" Margin="{Binding DaughtershipMargin}">
<i:Interaction.Behaviors>
<ei:MouseDragElementBehavior ConstrainToParentBounds="True" Dragging="MouseDragElementBehavior_Dragging"/>
</i:Interaction.Behaviors>
</local:colabdrag>
</Grid>
Edit:
I got this to work by creating a point relative to the draggable area and another point for the desired position based on that point, then using TranslateTranform to get the object where it needs to be
var pointA = (colabdragObject.TransformToAncestor(colabDragObjectGrid).Transform(new Point(X,Y))
var pointB = colabdragObjectGrid.TranslatePoint(pointA, colabDragObject);
colabdragObject.RenderTransform = new TranslateTransform(pointB.X, -1 * pointB.Y);

Wpf text rotation

I want to add some text on a canvas and decided to use textBlock for that (to set Font etc.)
But I cannot figure out how to rotate it.
I use the following function to add myText on myCanvas:
void text(double x_pos, double y_pos, string myText, double angle, Point rot_cen, Color color1)
{
TextBlock textBlock = new TextBlock()
{
Text = myText,
FontFamily = new FontFamily("Verdana"),
FontSize = 16,
TextAlignment = TextAlignment.Center
};
textBlock.Foreground = new SolidColorBrush(color1);
Canvas.SetLeft(textBlock, x_pos);
Canvas.SetTop(textBlock, y_pos);
textBlock.RenderTransform = new RotateTransform(angle, rot_cen.X, rot_cen.Y);
myCanvas.Children.Add(textBlock);
}
From what I've read rot_cen is a point from (0,0) - which is top left corner to (1,1) - which is bottom right corner. But when i set it to be (0.5,0.5) it still rotates around top left corner. Do I need to update it somehow?
The CenterX and CenterY properties of a RotateTransform use absolute coordinates.
You may want to set RenderTransformOrigin, which uses relative coordinates:
textBlock.RenderTransformOrigin = rot_cen;
textBlock.RenderTransform = new RotateTransform(angle);

WPF - How to work out how much of a canvas background image is cropped?

I have a canvas with a background image:
var bi = new BitmapImage(new Uri(imgLocFull));
var ib = new ImageBrush(bi) {Stretch = Stretch.UniformToFill};
MyCanvas.Background = ib;
I am overlaying various shapes on the image, and want the position of the shapes relative to the background image to be fixed.
If my application window is resized, the amount of the image that is cropped, horizontally and vertically, changes, and when my shapes are redrawn, they do not appear in the same position on the background image.
How can I determine how much of the image has been cropped (to apply an adjustment factor to the overlaid objects' positions?) Or is there a better way of fixing the location of a shape relative to the background image?
Here is my present drawing code:
var l = new Ellipse();
var scb = new SolidColorBrush();
scb.Color = Color.FromRgb(rCol, gCol, bCol);
l.Fill = scb;
l.StrokeThickness = 0;
l.Width = 3;
l.Height = 3;
Canvas.SetBottom(l, point.Y); // * clipping factor here?
Canvas.SetLeft(l, point.X); // * clipping factor here?
MyCanvas.Children.Add(l);
EDIT: Further Clarification
Here's a concrete example of what I am trying to achieve. My image is an aerial photograph, and I want to mark a particular geographical feature (with, say, an ellipse.)
When the window is resized, the ellipse doesn't stay on the feature, it stays relative to the left and top of the canvas.
I can get it closer to the right place by moving it using a factor (newx = newheight/oldheight * oldx) but this doesn't quite work because of the UniformToFill stretch mode, which sees some of the image clipped off the canvas.
The Top and Left of the Canvas are 'anchored', while the Bottom and Right move when resizing... try setting the Canvas.Top Attached Property instead, along with the Canvas.Left Attached Property as you are:
var l = new Ellipse();
var scb = new SolidColorBrush();
scb.Color = Color.FromRgb(rCol, gCol, bCol);
l.Fill = scb;
l.StrokeThickness = 0;
l.Width = 3;
l.Height = 3;
Canvas.SetTop(l, point.Y); // * clipping factor here?
Canvas.SetLeft(l, point.X); // * clipping factor here?
MyCanvas.Children.Add(l);
UPDATE >>>
You asked Or is there a better way of fixing the location of a shape relative to the background image?
I answered this question, so I don't understand why you would need to do anything else... your objects will not move when the screen in resized *if you only set the Grid.Top and Grid.Left properties.

Using Shift key Multi selection of checkbox( Find Controls within 2 points/ rectangle

In order to select multiple checkbox within Wrap panel using Shift Key.
Capturing the Mouse down event position on Shift Keydown, on second mouse down with shift keydown, getting the 2 positions of the selection, then Need to Select the checkbox control with in the selected area.
How do I find the controls within 2 positions (System.Window.Point) or System.Windows.rect. The following code is selecting all of the checkbox within the wrappanel(lesscolorpanel).
private System.Windows.Point startPoint;
System.Windows.Point checkpPoint;
private System.Windows.Point PointWhereMouseIs;
private void LessColourPanel_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
{
if (startPoint == checkpPoint)
{
//GET THE MOUSE POSITION
startPoint = Mouse.GetPosition(lessColourPanel);
PointWhereMouseIs = checkpPoint;
}
else if(PointWhereMouseIs==checkpPoint)
{
//CAPTURE END MOUSE POSITION
PointWhereMouseIs = Mouse.GetPosition(lessColourPanel);
//FIND CONTROLS WIHIN RECTANGLE
Rect selareaRect = new Rect(startPoint, PointWhereMouseIs);
foreach (System.Windows.Controls.CheckBox chkitemBox in FindVisualChildren<System.Windows.Controls.CheckBox>(lessColourPanel))
{
var rectBounds = VisualTreeHelper.GetDescendantBounds(chkitemBox);
Vector vector = VisualTreeHelper.GetOffset(chkitemBox);
rectBounds.Offset(vector);
if (rectBounds.IntersectsWith(selareaRect))
{
chkitemBox.IsChecked = true;
}
}
startPoint = checkpPoint;
}
}
}
Got it, and for viewers refer Ashley Davis post
The credit goes to Ashley Davis.

Silverlight specific Image shifting to the right

I am generating a set images to form a human body so that I can use for a physics engine.
The images generated are in a specific user control in where I set the dimentions and co-ordinates of each image. That usercontrol is then loaded in another user control but for some reason when the images are loaded, one specific image which I named (rightBicep) is shifting to the right. Here is a screenshot :
alt text http://img193.imageshack.us/img193/592/imageshift.jpg
I illustrated the positions of the images with dotted lines, the green dotted line is refering to where the image should be located, and the red dotted line is where the image is being shown.
The weird thing is the image beneath it (called rightForearm) take's it's LeftPosition from it, and when during debugging they have the exact same leftProperty value. Here's the syntax :
public void generateRightBicep(string imageUrl)
{
rightBicep = new Image();
rightBicep.Name = CharacterName + "rightbicep";
Uri imageUri = new Uri(imageUrl, UriKind.Relative);
LayoutRoot.Children.Add(rightBicep);
rightBicep.Source = new BitmapImage(imageUri);
rightBicep.ImageOpened += new EventHandler<RoutedEventArgs>(bodyPart_ImageOpened);
}
public void rightBicepLoaded()
{
var bi = waitTillImageLoad(rightBicep.Name);
rightBicep.Height = elbowToArmpit + (2 * palm);
rightBicep.Width = ratio(bi.PixelHeight, bi.PixelHeight, rightBicep.Height); // to be determined
Vector2 topVector;
topVector.X = (float)(Convert.ToDouble(torso.GetValue(Canvas.LeftProperty)) - palm);
topVector.Y = (float)(Convert.ToDouble(neck.GetValue(Canvas.TopProperty)) + neck.Height);
if (!faceRight)
{
perspectiveVectorHeight(ref topVector, ref rightBicep, torso.Width);
rightBicep.Width = ratio(bi.PixelHeight, bi.PixelHeight, rightBicep.Height);
}
rightBicep.SetValue(Canvas.LeftProperty, Convert.ToDouble(topVector.X));
rightBicep.SetValue(Canvas.TopProperty, Convert.ToDouble(topVector.Y));
rightBicep.SetValue(Canvas.ZIndexProperty, rightBicepZindex);
generateRightShoulder();
}
public void generateRightForearm(string imageUrl)
{
rightForearm = new Image();
rightForearm.Name = CharacterName + "rightforearm";
Uri imageUri = new Uri(imageUrl, UriKind.Relative);
LayoutRoot.Children.Add(rightForearm);
rightForearm.Source = new BitmapImage(imageUri);
rightForearm.ImageOpened += new EventHandler<RoutedEventArgs>(bodyPart_ImageOpened);
}
public void rightForearmLoaded()
{
var bi = waitTillImageLoad(rightForearm.Name);
rightForearm.Height = (elbowToHandTip - handLength) + palm;
rightForearm.Width = ratio(bi.PixelHeight, bi.PixelWidth, rightForearm.Height);
Vector2 topVector;
if (faceRight)
{
topVector.X = (float)(Convert.ToDouble(rightBicep.GetValue(Canvas.LeftProperty)));
topVector.Y = (float)(Convert.ToDouble(rightBicep.GetValue(Canvas.TopProperty)) + rightBicep.Height - palm);
}
else
{
topVector.X = (float)(Convert.ToDouble(leftBicep.GetValue(Canvas.LeftProperty)));
topVector.Y = (float)(Convert.ToDouble(leftBicep.GetValue(Canvas.TopProperty)) + leftBicep.Height - palm);
perspectiveVectorHeight(ref topVector, ref rightForearm, torso.Width);
rightForearm.Width = ratio(bi.PixelHeight, bi.PixelWidth, rightForearm.Height);
}
rightForearm.SetValue(Canvas.LeftProperty, Convert.ToDouble(topVector.X));
rightForearm.SetValue(Canvas.TopProperty, Convert.ToDouble(topVector.Y));
rightForearm.SetValue(Canvas.ZIndexProperty, rightForearmZIndex);
generateRightElbow();
}
Now all the values I am adding together are a group of doubles I preset, and the property faceRight is to dertmine if the human body is facing right or left to determine where the positions of the body parts (since if the right hand looks on the left hand side when the human body turns the other way).
If you notice the rightforearm is taking the leftproperty of the rightbicep, so technically it should display direcrly underneath which it isn't. I also debugged the user control and both have the left property of -3.
PS. I call the methods rightbicepLoaded and rightforearmLoaded when an event is called when all the imageOpened events all have been triggered.
Any ideas on why this is happening?
Found out why , in my method ratio it should take hieght and width, and I put and i put 2 hieghts instead

Resources