Unable to position Rectangle in Canvas in Silverlight 4 - silverlight

I'm new to SL. I just wrote a simple app drawing a Rectangle and Line. When I try to position the Rectangle it has no effect and always puts it in the lower-right corner:
Canvas.SetLeft(r, 100);
Canvas.SetTop(r, 100);
When I try to use SetValue, the app hangs (ie. get stuck on the loading animation in the browser):
r.SetValue(Canvas.LeftProperty, 10);
r.SetValue(Canvas.TopProperty, 10);
Has anyone experienced anything like this, and/or know how to get past it?
[EDIT] Here's the more complete source:
public MainPage()
{
InitializeComponent();
Rectangle r = new Rectangle() {
Stroke = new SolidColorBrush(Colors.Black),
Width = 100,
Height = 20,
Fill = new SolidColorBrush { Color = Color.FromArgb(80, 143, 12, 28) }
};
//r.SetValue(Canvas.LeftProperty, 10);
//r.SetValue(Canvas.TopProperty, 10);
Canvas.SetLeft(r, 100);
Canvas.SetTop(r, 100);
this.LayoutRoot.Children.Add(r);
var line = new Line() {
Stroke = new SolidColorBrush(Colors.Black),
X1 = 10, Y1 = 10, X2 = 100, Y2 = 200
};
LayoutRoot.Children.Add(line);
}
I've tried putting the LayoutRoot..Add call before the SetValue/SetLeft but it doesn't seem to make any difference.

Try this :
this.LayoutRoot.Children.Add(r);
Canvas.SetLeft(r, 100);
Canvas.SetTop(r, 100);
Rather than:
Canvas.SetLeft(r, 100);
Canvas.SetTop(r, 100);
this.LayoutRoot.Children.Add(r);
Update : It got fixed since in XAML it is by default a grid tag as LayoutRoot. After changing it to a canvas tag and it no longer gets stuck.

Related

How to have a second color for a drawing group in wpf

I need to be able to draw horizontal lines against a background color, say red. I have the lines being drawn, but I don't know how to set the background color. Right now, the background is white.
GeometryGroup stdGeometryGroup = new GeometryGroup();
DrawingBrush db = new DrawingBrush();
GeometryDrawing stdDrawing = new GeometryDrawing(null, pen, stdGeometryGroup);
if (stdDrawing != null)
{
db.Drawing = stdDrawing;
db.ViewboxUnits = BrushMappingMode.Absolute;
db.ViewportUnits = BrushMappingMode.Absolute;
db.Viewbox = new Rect(0, 0, 30, 30);
db.Viewport = new Rect(0, 0, 4, 4);
db.TileMode = TileMode.Tile;
db.Stretch = Stretch.UniformToFill;
db.Transform = new RotateTransform(45, 0.5, 0.5);
stdGeometryGroup.Children.Add(new LineGeometry(new Point(0, 15), new Point(30, 15)));
menuItem.Background = db;
}
In this case, menuItem is a Telerik RadMenuItem. The Pen is black.

Rendering DashStyle.Dot Line using Graphics.PageScale as 0.50

In Windows form, I am trying to render the Line by setting style as DashStyle.Dot by using Graphics and Graphics page scale as 0.50. But the line does not rendered in form. Please anyone suggest me on this....
refer to the below code snippet:
protected override void OnPaint(PaintEventArgs e)
{
gp = e.Graphics;
gp.PageScale = 0.50f;
using (System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.White))
{
gp.FillRectangle(myBrush, new RectangleF(30, 100, 400, 600));
}
// Create pen.
using (Pen blackPen = new Pen(Color.Black, 0))
{
blackPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
gp.DrawLine(blackPen, 30, 200, 430, 200);
}
}
I believe it's being drawn but it has too small width so it's practically invisible.
Try another width, similar to:
using (Pen blackPen = new Pen(Color.Black, 4.0F))
{
blackPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
gp.DrawLine(blackPen, 30, 200, 430, 200);
}

Scaling and moving an item at the same time

I'm trying to create a storyboard that scales and moves an element to a specific position. The basic idea is there are a row of 6 small cards, clicking on one will zoom into a more detailed image, starting from the position and size of the small card and ending up with a large centered card.
The card doesn't end up in the X,Y position I specify, I believe because the scaletransform is also moving it. I saw that a matrixtransform may work, but couldn't get it to work, at least in WP8. Here is my original code, card is the small card for starting location, item is the large detailed card to be scaled and moved
private void ZoomIn(UIElement item, UIElement card)
{
// setup
var _Scale = new ScaleTransform
{
ScaleX = 1,
ScaleY = 1,
CenterX = item.RenderSize.Width / 2,
CenterY = item.RenderSize.Height / 2,
};
var transform = card.TransformToVisual(Application.Current.RootVisual as FrameworkElement);
Point absolutePosition = transform.Transform(new Point(0, 0));
var _Translate = new TranslateTransform();
var _Group = new TransformGroup();
_Group.Children.Add(_Scale);
_Group.Children.Add(_Translate);
item.RenderTransform = _Group;
// animate
var _Storyboard = new Storyboard { };
// scale X
var _ScaleAnimateX = new DoubleAnimation
{
To = 1.0,
From=0.5,
Duration = TimeSpan.FromSeconds(.25)
};
_Storyboard.Children.Add(_ScaleAnimateX);
Storyboard.SetTarget(_ScaleAnimateX, _Scale);
Storyboard.SetTargetProperty(_ScaleAnimateX,
new PropertyPath(ScaleTransform.ScaleXProperty));
// scale Y
var _ScaleAnimateY = new DoubleAnimation
{
To = 1.0,
From = 0.5,
Duration = TimeSpan.FromSeconds(.25)
};
_Storyboard.Children.Add(_ScaleAnimateY);
Storyboard.SetTarget(_ScaleAnimateY, _Scale);
Storyboard.SetTargetProperty(_ScaleAnimateY,
new PropertyPath(ScaleTransform.ScaleYProperty));
// translate (location X)
var _TranslateAnimateX = new DoubleAnimation
{
From = absolutePosition.X,
To = 300,
Duration = TimeSpan.FromSeconds(.25)
};
_Storyboard.Children.Add(_TranslateAnimateX);
Storyboard.SetTarget(_TranslateAnimateX, _Translate);
Storyboard.SetTargetProperty(_TranslateAnimateX,
new PropertyPath(TranslateTransform.XProperty));
// translate (location Y)
var _TranslateAnimateY = new DoubleAnimation
{
From = absolutePosition.Y,
To = 40,
Duration = TimeSpan.FromSeconds(.25)
};
_Storyboard.Begin();
}
I found the solution, the panel with the zoomed card didn't have a horizontal/vertical alignment, I set it to left/top, used CenterX/CenterY of 0, and movements are now pixel perfect

Wpf canvas refresh

I'm wondering if there is a way to refresh canvas before adding a child item to it?
I have this code, it draw me a black ellipse with light blue stroke. Now I want to change StrokeThickness when program is launched (I have a slider to define StrokeThickness). The problem is that StrokeThickness is changed but only if I redraw ellipse, but I want that change is made when I move my slider. Any ideas? Thanks!
//this code is in canvas_MouseDown
double smt = sliderThickness.Value;
//krog
elip = new Ellipse
{
Width = 100,
Height = 100,
Fill = Brushes.Black,
Stroke = Brushes.LightBlue,
StrokeThickness = smt,
};
Canvas.SetLeft(elip, mouseX - 50);
Canvas.SetTop(elip, mouseY - 50);
canvas1.Children.Add(elip);
in slider value Changedevent u have to put following code
private void sliderThickness_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
foreach (var item in canvas1.Children)
{
if (item is Ellipse)
{
var elip = item as Ellipse;
elip.StrokeThickness = sliderThickness.Value;
}
}
}
Or shorter
// using System.Linq;
foreach (var ellipse in canvas1.Children.OfType<Ellipse>())
{
ellipse.StrokeThickness = sliderThickness.Value;
}

passing a vector drawing to the UI thread

Is there any way to draw actual WPF vectorgraphics (DrawingContext, VisualBrush, DrawingBrush, RenderTargetBitmap etc.) with Freezables in a separate thread offscreen?
The following solution almost has it, excpet that the drawing is a bitmap and is not scalable when this.label becomes big you'll the the pixels.
private void Draw()
{
this.dispatcher = Dispatcher.CurrentDispatcher;
Thread t = new Thread(this.DrawAsync);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void DrawAsync(object state)
{
var b1 = new Button
{
Width = 50,
Height = 50,
Content = new TextBlock
{
FontSize = 16, FontFamily = new FontFamily("Arial"), FontWeight = FontWeights.Bold, Text = "Hello"
}
};
b1.Measure(new Size(50, 50));
b1.Arrange(new Rect(0, 0, 50, 50));
PixelFormat pixelFormat = PixelFormats.Default;
var elementBrush = new VisualBrush(b1);
var visual = new DrawingVisual();
using (var dc = visual.RenderOpen())
{
// preferably I'd like to draw controls too, but shapes and text would suffice too
dc.DrawRectangle(elementBrush, null, new Rect(0, 0, 50, 50));
dc.DrawEllipse(Brushes.Green, new Pen(Brushes.Black, 2), new Point(75, 25), 25, 15);
dc.Close();
}
var bitmap = new RenderTargetBitmap(100, 50, 96, 96, pixelFormat);
bitmap.Render(visual);
bitmap.Freeze();
var br = new ImageBrush(bitmap) { Stretch = Stretch.Uniform };
br.Freeze();
this.dispatcher.Invoke((ThreadStart)delegate { this.label.Background = br; });
}
You could use DrawingImage which is a type of freezeable. Load or fill it in a BackgroundWorker, freeze it and pass it to an Image in the Completed Event.

Resources