Get rectangles from the Canvas - c#

I am working on a windows phone project. I would like to use a function for my collision.
this is the code I use:
foreach (Rectangle mrec in mCanvas.Children)
{
if (my_ellipse.Margin.Top + my_ellipse.Height > mrec.Margin.Top && my_ellipse.Margin.Top <= mrec.Margin.Top + mrec.Height && my_ellipse.Margin.Left + my_ellipse.Width >= mrec.Margin.Left && my_ellipse.Margin.Left <= mrec.Margin.Left + mrec.Width)
{
my_ellipse.Fill = new SolidColorBrush(Colors.Green);
}
else
{
my_ellipse.Fill = new SolidColorBrush(Colors.White);
}
}
But when I use this, the foreach loop does not only grabs the Rectangle elements. It also grabs the TextBlock and the Ellipse.
I hope somebody can help me with this problem.

The problem here is that Children contains objects that are not of type Rectangle your foreach is attempting to cast each item in Children to Rectangle. Instead you need to test if each item is a Rectangle first.
foreach (var child in mCanvas.Children)
{
Rectangle mrec = child as Rectangle;
if(mrec != null)
{
// Your logic here
}
}
Alternatively you can use Enumerable.OfType to do the filtering.
foreach (Rectangle mrec in mCanvas.Children.OfType<Rectangle>())
{
// Your logic here
}

Related

How to make Win2D BlendEffect apply to current drawing surface (background)?

I want to draw some images on to existing canvas using multiply blend mode. However, I don't know how to do it as the BlendEffect class require me to assign the Background variable but that is suppose to be the canvas which I could not put there.
private void OnDrawCanvas(CanvasControl sender, CanvasDrawEventArgs args)
{
var list = new LinkedList<ImageNode>();
mRootNode.GetTraverseList(list, false);
foreach (var item in list)
{
if (!item.treeVisible)
continue;
if (item.mLayerPixels != null)
{
if (item.mLayer.BlendModeKey == BlendModeType.MULTIPLY)
{
var blendEffect = new BlendEffect()
{
//Background = ???, // what to put????
Foreground = item.mLayerPixels,
Mode = BlendEffectMode.Multiply
};
args.DrawingSession.DrawImage(blendEffect, item.mLayer.Left, item.mLayer.Top);
}
else
{
args.DrawingSession.DrawImage(item.mLayerPixels, item.mLayer.Left, item.mLayer.Top);
}
}
}
}
I ended up creating an offscreen CanvasRenderTarget to do the blending. When all the drawing is done, I create a CanvasBitmap from CanvasRenderTarget which allow me to draw the final result to the UI with args.DrawingSession.DrawImage();

Xamarin iOS - AddOverlays() only adding first polygon

I am following this tutorial for adding polygons onto a map in Xamarin. I am currently implementing the iOS section of this tutorial, but because I want to add multiple polygons to my map instead of the single polygon shown in the tutorial, I am using the addOverlays() function which takes in an array of IMKOverlay objects, instead of the addOverlay() function which takes 1 IMKOverlay object.
For some reason all of my polygons are being plotted at the same coordinates as my first polygon in my List, similar to an issue this person had!
Here is my code:
void addPolygonsToMap()
{
overlayList = new List<IMKOverlay>();
for (int i = 0; i < polygons.Count; i++)
{
CLLocationCoordinate2D[] coords = new CLLocationCoordinate2D[polygons[i].Count];
int index=0;
foreach (var position in polygons[i])
{
coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude);
index++;
}
var blockOverlay = MKPolygon.FromCoordinates(coords);
overlayList.Add(blockOverlay);
}
IMKOverlay[] imko = overlayList.ToArray();
nativeMap.AddOverlays(imko);
}
You have to edit the code in MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper) which is in the tutorial. Just remove the if statement or remove the polygonRenderer == null && in the if statement, like this:
MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
{
if (!Equals(overlayWrapper, null))
{
var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
polygonRenderer = new MKPolygonRenderer(overlay as MKPolygon)
{
FillColor = UIColor.Red,
StrokeColor = UIColor.Blue,
Alpha = 0.4f,
LineWidth = 9
};
}
return polygonRenderer;
}
Otherwise, it will always return the first polygonRenderer which is including your first coordinates group.

All control property change in loop

I'm writing a code to apply transparent background to all of my LinkLabel controls. I don't wanna do it with hardcoded label id and repeating the same code.
foreach (Control cType in this.Controls)
{
if (cType.GetType() == typeof(LinkLabel))
{
LinkLabel linkTemp = cType as LinkLabel;
Point pos = this.PointToScreen(linkTemp.Location);
pos = pictureBox1.PointToClient(pos);
linkTemp.Parent = pictureBox1;
linkTemp.Location = pos;
linkTemp.BackColor = Color.Transparent;
}
}
When I'm trying the above piece of code it make odd numbered buttons to be transparent i.e.
Button 1 - transparent
Button 2 - NOT
Button 3 - transparent
But while I'm repeating the same code applied on different linklabel ids manually its working fine. What I'm missing here?
This is an inevitable side-effect of you changing the Parent property of the control. That modifies the Controls collection since the LinkLabel is moved from the form's Controls collection to the pictureBox1.Controls collection. Modifying a collection while iterating it normally generates an InvalidOperationException but this was not done for the Controls collection.
You need to solve this by iterating the collection backwards. Like this:
for (int ix = this.Controls.Count-1; ix >= 0; --ix) {
var linkTemp = this.Controls[ix] as LinkLabel;
if (linkTemp == null) continue;
// etc..
}
Some programmers like using Linq, that's okay too but obfuscates the issue a bit and isn't nearly as efficient. Key is to make a copy that cannot be affected by modifying the collection:
foreach (var linkTemp in this.Controls.OfType<LinkLabel>().ToList()) {
// etc..
}
You can use this 'odd' construction:
int i = 1;
foreach (LinkLabel item in this.Controls.OfType<LinkLabel>())
{
if ((i = 1 - i) == 0)
{
LinkLabel linkTemp = cType as LinkLabel;
Point pos = this.PointToScreen(linkTemp.Location);
pos = pictureBox1.PointToClient(pos);
linkTemp.Parent = pictureBox1;
linkTemp.Location = pos;
linkTemp.BackColor = Color.Transparent;
}
}
Some tips for code formatting
Change
if (cType.GetType() == typeof(LinkLabel))
to
if (cType is LinkLabel)
Change
foreach (Control cType in this.Controls)
{
if (cType.GetType() == typeof(LinkLabel))
{
LinkLabel linkTemp = cType as LinkLabel;
Point pos = this.PointToScreen(linkTemp.Location);
pos = pictureBox1.PointToClient(pos);
linkTemp.Parent = pictureBox1;
linkTemp.Location = pos;
linkTemp.BackColor = Color.Transparent;
}
}
to
foreach (LinkLabel linkTemp in this.Controls.OfType<LinkLabel>())
{
Point pos = this.PointToScreen(linkTemp.Location);
pos = pictureBox1.PointToClient(pos);
linkTemp.Parent = pictureBox1;
linkTemp.Location = pos;
linkTemp.BackColor = Color.Transparent;
}

Dynamically altering the image source of a canvas object

I have an animation that is ran on a timer along with some other animations. I would like to be able to change the images source file when an event is triggered but i am currently unable to access element.Source (element equaling the current canvas object which is a image).
public static void Clouds(Canvas canvas, int boundry)
{
var random = new Random();
foreach (FrameworkElement element in canvas.Children)
{
var elementName = Regex.Split(element.Name, "_");
if (elementName[0] == "cloud")
{
if (Canvas.GetLeft(element) < canvas.ActualWidth + element.Width)
{
Canvas.SetLeft(element, Canvas.GetLeft(element) + 1);
} else
{
// Change image source file here.
Canvas.SetTop(element, random.Next(0 - ((int)element.Height / 2), Core.GetPercentage((int)canvas.ActualHeight, boundry)));
Canvas.SetLeft(element, 0 - element.Width);
}
}
}
}
Any help would be great, thanks.
Its because FrameworkElement has no property called Source, you have to cast or just pick the image elements you want.
Somthing like this may work
public static void Clouds(Canvas canvas, int boundry)
{
var random = new Random();
foreach (var image in canvas.Children.OfType<Image>())
{
if (image.Name.Contains("cloud_"))
{
if (Canvas.GetLeft(image) < canvas.ActualWidth + image.Width)
{
Canvas.SetLeft(image, Canvas.GetLeft(image) + 1);
}
else
{
Canvas.SetTop(image, random.Next(0 - ((int)image.Height / 2), Core.GetPercentage((int)canvas.ActualHeight, boundry)));
Canvas.SetLeft(image, 0 - image.Width);
}
}
}
}
now you will be able to access the source property as the var "image" is an Image

Removing Elements Programmatically in Silverlight

I am starting to learn silverlight and to practice I am doing a simple space invaders type videogame.
My issue is I am creating custom controls (bullets) programmatically like so:
if(shooting)
{
if(currBulletRate == bulletRate)
{
Bullet aBullet = new Bullet();
aBullet.X = mouse.X - 5;
aBullet.Y = mouse.Y - Ship.Height;
aBullet.Width = 10;
aBullet.Height = 40;
aBullet.Tag = "Bullet";
LayoutRoot.Children.Add(aBullet);
currBulletRate = 0;
}
else
currBulletRate++;
}
However I am having trouble removing them once they go off bounds (leave the LayoutRoot).
I tried looping throught the LayoutRoot.Children and removing but I can't seem to get it right.
UIElement[] tmp = new UIElement[LayoutRoot.Children.Count];
LayoutRoot.Children.CopyTo(tmp, 0);
foreach (UIElement aElement in tmp)
{
Shape aShape = aElement as Shape;
if (aShape != null && aShape.Tag != null)
{
if (aShape.Tag.ToString().Contains("Bullet"))
{
if (Canvas.GetTop(aShape) + aShape.ActualHeight < 0) // This checks if it leaves the top
{
LayoutRoot.Children.Remove(aElement);
}
else if(Canvas.GetTop(aShape) > Canvas.ActualHeight) // This condition checks if it leaves the bottom
{
LayoutRoot.Children.Remove(aElement);
}
}
}
}
The code you pasted was only checking if the bullet left the top of the canvas.

Categories