WPF adding rectangles on canvas - c#

The code below does not adding rectangle. Can anyone advice What i missed ? mainCanvas.Children.Add(rectangle[i]); does not work.
RoomX.Count = 5 how I can go with for add all five rectangles with different width and height which is in RoomX, RoomY
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
HProDataContext db = new HProDataContext();
var RoomX = (from d in db.rooms select d.sizex).ToList();
var RoomY = (from d in db.rooms select d.sizey).ToList();
for (int i = 0; i < RoomX.Count; i++)
{
var random = new Random();
var rectangle = new Rectangle()
{
Stroke = Brushes.Black,
Fill = Brushes.SkyBlue,
Width = Convert.ToDouble(RoomX),
Height = Convert.ToDouble(RoomY),
Margin = new Thickness(left: random.NextDouble() * 300,
top: random.NextDouble() * 150,
right: 0,
bottom: 0),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
};
mainCanvas.Children.Add(rectangle);
}
}

Width = Convert.ToDouble(RoomX),
Height = Convert.ToDouble(RoomY),
Are you sure that's what you want to do? You're converting a list to a double there, which seems kinda off.
I think you need something like:
Width = Convert.ToDouble(RoomX[i]),
Height = Convert.ToDouble(RoomY[i]),

Related

How to get Canvas to scroll in WinUI 3?

I am unable to get the ScrollBars to appear for a Canvas when its children are out of view. This is being directly added to the MainWindow.
<ScrollViewer>
<Canvas x:Name="MainCanvas"/>
</ScrollViewer>
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
for (int i = 0; i < 20; i++)
{
var rect = new Rectangle()
{
Height = 100,
Width = 200,
Stroke = new SolidColorBrush(Colors.Magenta)
};
Canvas.SetLeft(rect, (i * 200) + 10);
Canvas.SetTop(rect, 10);
var rect1 = new Rectangle()
{
Height = 100,
Width = 200,
Stroke = new SolidColorBrush(Colors.DarkOrchid)
};
Canvas.SetLeft(rect1, 10);
Canvas.SetTop(rect1, (i * 100) + 10);
MainCanvas.Children.Add(rect);
MainCanvas.Children.Add(rect1);
}
}
So, children are being added that go out of view horizontally and vertically. I've tried various settings for scrollbar visibility, alignments, etc. but just cant get the scrollbars to appear. Thanks for any inputs.
Specify a size for the Canvas so the ScrollViewer can measure it:
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
MainCanvas.Width = 0;
MainCanvas.Height = 0;
for (int i = 0; i < 20; i++)
{
var rect = new Rectangle()
{
Height = 100,
Width = 200,
Stroke = new SolidColorBrush(Colors.Magenta)
};
double left = (i * 200) + 10;
MainCanvas.Width = left;
Canvas.SetLeft(rect, left);
Canvas.SetTop(rect, 10);
var rect1 = new Rectangle()
{
Height = 100,
Width = 200,
Stroke = new SolidColorBrush(Colors.DarkOrchid)
};
double top = (i * 100) + 10;
MainCanvas.Height = top;
Canvas.SetLeft(rect1, 10);
Canvas.SetTop(rect1, top);
MainCanvas.Children.Add(rect);
MainCanvas.Children.Add(rect1);
}
}
You may also want to enable horizontal scrolling:
<ScrollViewer HorizontalScrollBarVisibility="Auto">
...

Slow performance using dashed lines on Canvas

I need to create a grid using Canvas with horizontal and vertical lines. The problem is in very bad performance when I'm using dashed lines instead of solid. Is there any solution to solve this? I don't need the possibility to handle events of this dashed lines (maybe exists some 'lightweight' version of canvas object...).
If I add StrokeDashArray to the Line object the application is very slow...
private void DrawGrid()
{
var brush = new SolidColorBrush((Color) ColorConverter.ConvertFromString("#cccccc"));
for (int i = 100; i < _areaSize; i += 100)
{
var hLine = new Line
{
X1 = 0,
Y1 = i,
X2 = _areaSize,
Y2 = i,
Stroke = brush,
StrokeThickness = 1,
SnapsToDevicePixels = true,
};
var vLine = new Line
{
X1 = i,
Y1 = 0,
X2 = i,
Y2 = _areaSize,
Stroke = brush,
StrokeThickness = 1,
SnapsToDevicePixels = true
};
//hLine.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
//vLine.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
Container.Children.Add(hLine);
Container.Children.Add(vLine);
Panel.SetZIndex(hLine, -1000);
Panel.SetZIndex(vLine, -1000);
}
}

Draw rectangle WP8.1 async (or fast)

I'm trying to draw rectangles into a WriteableBitmap, unfortunatelly the WriteableBitmapEx that provides Fill* extensions are too slow and can be run only at the main thread.
I'm looking for alternatives specific for WP8.1 and don't know the best solution so far.
I need a way to draw the rectangles async, one approach was creating a Canvas at the MainWindow and adding xaml.Rectangles on it, this almost can be used as solution for the problem, but I want specific draw the rectangles on the WriteableBitmap instead of creating a ton of UIElements and adding all of then on the screen.
Sorry if any given solution can be found on internet, I can't find almost nothing about C#.
A test I did:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var container = new Canvas()
{
Width = 300,
Height = 500
};
var winImage = new Image()
{
Width = 300,
Height = 500
};
container.Children.Add(winImage);
//var winImage = imageView.NativeView<Image>();
var img = new WriteableBitmap((int)winImage.Width, (int)winImage.Height);
var clr = Color.FromArgb(255, 0, 0, 255);
var start = DateTime.Now;
var random = new Random();
for (int i = 0; i < 50; i++)
{
//var color = Color.FromArgb(255, (byte)random.Next(255), (byte)random.Next(255), (byte)random.Next(255));
img.FillRectangle(i * 2, i * 2, i * 2 + 10, i * 2 + 10, clr);
}
Debug.WriteLine((DateTime.Now - start).TotalMilliseconds + "ms drawing");
winImage.Source = img;
Content = container;
}
This results in "792.1397ms drawing" running on debug mode on a Nokia Lumia 1020, that is pretty slow.
Using GetBitmapContext() should make it a lot faster.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var container = new Canvas()
{
Width = 300,
Height = 500
};
var winImage = new Image()
{
Width = 300,
Height = 500
};
container.Children.Add(winImage);
var img = BitmapFactory.New((int)winImage.Width, (int)winImage.Height);
winImage.Source = img;
Content = container;
var clr = Color.FromArgb(255, 0, 0, 255);
var random = new Random();
var sw = new Stopwatch();
sw.Start();
using (img.GetBitmapContext()) {
img.Clear(Colors.White);
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
img.FillRectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10, clr);
}
}
}
sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds + "ms drawing");
}

Printing Image from Silverlight

I'm trying to print a Image in Landscape mode in Silverlight.
I found a great example here. Where most of the code comes from. The code worked perfectly as expected. When I changed the Line to an Image it failed.
Code
Canvas OuterCanvas = new Canvas();
/* a container for everything that will print */
Border OuterBorder = new Border()
{
BorderThickness = new Thickness(3),
BorderBrush = new SolidColorBrush(Colors.Red),
Margin = new Thickness(10)
};
double Width = e.PrintableArea.Width - OuterBorder.Margin.Left - OuterBorder.Margin.Right;
double Height = e.PrintableArea.Height - OuterBorder.Margin.Top - OuterBorder.Margin.Bottom;
/* NOTE: We're trying to force landscape, so swop the width and height */
OuterBorder.Width = Height;
OuterBorder.Height = Width;
/* on portrait, this line goes down (leave the printer settings, we're trying to force landscape) */
Line Line = new Line()
{
X1 = OuterBorder.Width / 2,
Y1 = 0,
X2 = OuterBorder.Width / 2,
Y2 = OuterBorder.Height,
Stroke = new SolidColorBrush(Colors.Blue),
StrokeThickness = 3
};
//
// Here is where I changed the Line to an Image
//
OuterBorder.Child = imageElementInXaml; //Line;
OuterCanvas.Children.Add(OuterBorder);
/* rotate 90 degrees, and move into place */
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new RotateTransform() { Angle = 90 });
transformGroup.Children.Add(new TranslateTransform() { X = e.PrintableArea.Width });
OuterBorder.RenderTransform = transformGroup;
e.PageVisual = OuterCanvas;
e.HasMorePages = false;
I know that a Border can only contain 1 element in which I have done so, and when I printed the image on its own without trying to make it landscape this worked too. So why wont it work when I simply replace the Line with the image Element
So since posting this I found some code (cant remember where now) that has helped me get the printing working. Its not as clean as I would have liked but it works.
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Image image = new Image();
image.Source = imgPlayer.Source;
//This is important
image.Stretch = Stretch.Uniform;
// Find the full size of the page
Size pageSize = new Size(e.PrintableArea.Width + e.PageMargins.Left + e.PageMargins.Right, e.PrintableArea.Height + e.PageMargins.Top + e.PageMargins.Bottom);
var MARGIN= 10;
// Get additional margins to bring the total to MARGIN (= 96)
Thickness additionalMargin = new Thickness
{
Left = Math.Max(0, MARGIN - e.PageMargins.Left),
Top = Math.Max(0, MARGIN - e.PageMargins.Top),
Right = Math.Max(0, MARGIN - e.PageMargins.Right),
Bottom = Math.Max(0, MARGIN - e.PageMargins.Bottom)
};
// Find the area for display purposes
Size displayArea = new Size(e.PrintableArea.Width - additionalMargin.Left - additionalMargin.Right, e.PrintableArea.Height - additionalMargin.Top - additionalMargin.Bottom);
bool pageIsLandscape = displayArea.Width > displayArea.Height;
bool imageIsLandscape = image.ActualWidth > image.ActualHeight;
double displayAspectRatio = displayArea.Width / displayArea.Height;
double imageAspectRatio = (double)image.ActualWidth / image.ActualHeight;
double scaleX = Math.Min(1, imageAspectRatio / displayAspectRatio);
double scaleY = Math.Min(1, displayAspectRatio / imageAspectRatio);
// Calculate the transform matrix
MatrixTransform transform = new MatrixTransform();
if (pageIsLandscape == imageIsLandscape)
{
// Pure scaling
transform.Matrix = new Matrix(scaleX, 0, 0, scaleY, 0, 0);
}
else
{
// Scaling with rotation
scaleX *= pageIsLandscape ? displayAspectRatio : 1 / displayAspectRatio;
scaleY *= pageIsLandscape ? displayAspectRatio : 1 / displayAspectRatio;
transform.Matrix = new Matrix(0, scaleX, -scaleY, 0, 0, 0);
}
Image image2 = new Image
{
Source = image.Source,
Stretch = Stretch.Fill,
Width = displayArea.Width,
Height = displayArea.Height,
RenderTransform = transform,
RenderTransformOrigin = new Point(0.5, 0.5),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Margin = additionalMargin,
};
Border border = new Border
{
Child = image,
};
e.PageVisual = border;
}

How to correctly save UIControl with opacity to WriteableBitmap?

I make group of rectangles with different opacity value and add these rectangles to Grid in WindowsPhone:
var grid=new Grid();
grid.Width = grid.Height = 200;
var rectanglesCount=55;
var rectangleSizeStep = grid.Height / rectanglesCount;
var opacityStep = 1.0 / rectanglesCount
var rectangleSize = grid.Height;
var opacity = 0.0;
for (int i = 0; i <= rectanglesCount; i++)
{
Rectangle rect = new Rectangle();
rect.Height = rect.Width = rectangleSize;
rect.VerticalAlignment = VerticalAlignment.Center;
rect.HorizontalAlignment = HorizontalAlignment.Center;
rect.Fill = new SolidColorBrush(Colors.Yellow);
rect.Opacity = opacity;
opacity += opacityStep;
rectangleSize -= rectangleSizeStep;
grid.Children.Add(rect);
}
I can see in grid following picture:
After I try to save this group of rectangles to WriteableBitmap and show as Image:
var img=new Image();
var wrBit = new WriteableBitmap(grid, null);
img.Source=wrBit;
And I see picture:
What happend with opacity on top and left edges?
How to correctly save group of Rectangles?
Need to use Canvas instead Grid control for group of rectangles:
var canvas=new Canvas();
canvas.Width = canvas.Height = 200;
var rectanglesCount=55;
var rectangleSizeStep = canvas.Height / rectanglesCount;
var opacityStep = 1.0 / rectanglesCount
var rectangleSize = canvas.Height;
var opacity = 0.0;
var rectMargin = 0.0;
for (int i = 0; i <= rectanglesCount; i++)
{
Rectangle rect = new Rectangle();
rect.Height = rect.Width = rectangleSize;
rect.Margin=new Thickness(rectMargin,rectMargin,0,0);
rectMargin += rectangleSizeStep/2;
rect.Fill = new SolidColorBrush(Colors.Yellow);
rect.Opacity = opacity;
opacity += opacityStep;
rectangleSize -= rectangleSizeStep;
canvas.Children.Add(rect);
}
and save Canvas as WriteableBitmap:
var img=new Image();
var wrBit = new WriteableBitmap(canvas, null);
img.Source=wrBit;
Problem was solved!

Categories