How do I reference a rectangle created programmatically, with XAML? - c#

I am working with WPF for the first time. I am creating a rectangle object & adding it as a child of a canvas.
How do I reference it in XAML?
I want to be able to rotate it over time but don't know how to access it from the MainWindow.xaml code...
I haven't been able to find an answer to this anywhere (maybe you can't do it this way?)
Edit:
I tried setting the Name property of the rectangle to Test (in C# code) and then doing
<Rectangle x:Name="Test">
<Rectangle.LayoutTransform>
<RotateTransform Angle="-45"/>
</Rectangle.LayoutTransform>
</Rectangle>
(This didn't work)

If you create a control in C#, you cannot access it in XAML. I think you must create the necessary animation in C# too.
Applying your rotation in C# could look like this:
var rect = new Rectangle();
rect.LayoutTransform = new RotateTransform() { Angle = -45 };
parentPanel.Children.Add(rect);
The better way would be to generate the Rectangle in XAML and apply there the animation. But this depends on your exact situation. e.g. you can create a single Rectangle in XAML and use this one or you can bind an ItemsControl and create a Rectangle in the ItemTemplate for each entry in the binded list.

Related

UWP: Create shadow in XAML [duplicate]

This question already has an answer here:
Drop Shadow effect in Universal Windows Application
(1 answer)
Closed 5 years ago.
I am currently trying to create a circular button with two ellipse-elements in UWP and want one of them to throw a shadow at a certain angle. I found a way to do so in WPF which looks like this:
WPF XAML:
<Ellipse>
<Ellipse.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="-50" ShadowDepth="50" Softness=".7"/>
</Ellipse.BitmapEffect>
</Ellipse>
What's the equivalent in UWP?
The easiest way is to use the DropShadowPanel from UWP Community Toolkit.
So first just install
Install-Package Microsoft.Toolkit.Uwp.UI.Controls -Version 2.0.0
Then use the following code in your XAML
<controls:DropShadowPanel Color="Black"
OffsetX="-50"
OffsetY="-50"
BlurRadius="50"
ShadowOpacity=".7"
Width="120"
Height="120"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch">
<Ellipse />
</controls:DropShadowPanel>
In UWP there is a different component to do this job. It's called the Composition API and is available in the NuGet Package "Win2D.uwp".
Basically you'll need to get the compositor for your visual object with
_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
and create a drop shadow using the compositor.
_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
// create a red sprite visual
var myVisual = _compositor.CreateSpriteVisual();
myVisual.Brush = _compositor.CreateColorBrush(Colors.Red);
myVisual.Size = new System.Numerics.Vector2(100, 100);
// create a blue drop shadow
var shadow = _compositor.CreateDropShadow();
shadow.Offset = new System.Numerics.Vector3(30, 30, 0);
shadow.Color = Colors.Blue;
myVisual.Shadow = shadow;
// render on page
ElementCompositionPreview.SetElementChildVisual(this, myVisual);
The downside beeing, that this is not quite straight forward. You can use different brushes to display images, solid colors or other stuff, it won't apply to existing visuals on screen (as far as I understand it). You can read more about the basics here. Probalby you'll need to use a surface brush, which can hold a wide variety of different visual types, like images. Currently it does not look like there is a ready made component for ellipses though.
Alternatively there exists a xaml extension which will do all that stuff for you using pure xaml, might be worth a shot and maybe also support ellipses.
As an ending note, all of this is currently a work in progress on microsofts part and should become a native part of the UWP API in the future.

Creating and Accessing a GeometryGroup in CodeBehind

i'm new in the StackOverflow Community and please excuse my bad english, i try to imrpove it.
I am using your help for my bachelorthesis and you helped me already a lot, thanks. I am writing a tool to visualize data in wireless networks.
I add a GeometryGroup to my Canvas to connect some of my CustomControls with a line. The line is being updated, when the control is moved etc. I've used the following article: https://denisvuyka.wordpress.com/2007/10/21/wpf-diagramming-drawing-a-connection-line-between-two-elements-with-mouse/ to make it work.
This is the code i use in my XAML.
<Path Name="myPath" Stroke="#FF132FE0" StrokeThickness="1">
<Path.Data>
<GeometryGroup x:Name="connectors"/>
</Path.Data>
</Path>
What i am trying to do is to create my own canvas class and add the GeometryGroup in the code behind. What i tried to do was:
System.Windows.Shapes.Path pathGroup= new System.Windows.Shapes.Path();
BrushConverter bc = new BrushConverter();
Brush Brush = (Brush)bc.ConvertFrom("#FF132FE0");
cmp.Stroke = Brush;
cmp.StrokeThickness = 1;
GeometryGroup connectors= new GeometryGroup();
pathGroup.Data=connectors;
My Problem is, that it didn't workt as intended. With the XAML implementation i can just use the following:
connectors.Children.Add(obj);
I try to to sum up my problem. I would like to create with c#-code a GeometryGroup to be able to add and remove lines, whenever i want it.
Thank you =)
You might want to have a derived Canvas with a connectors field (similar to the one created from the XAML shown in your question).
The Canvas would draw the connectors by means of an overridden OnRender method like shown below.
public class CustomCanvas : Canvas
{
private readonly GeometryGroup connectors = new GeometryGroup();
protected override void OnRender(DrawingContext dc)
{
var stroke = new SolidColorBrush(Color.FromRgb(0x13, 0x2F, 0xE0));
dc.DrawGeometry(null, new Pen(stroke, 1), connectors);
base.OnRender(dc);
}
}
Some additional code in another method of the derived Canvas class would now add or remove Geometry objects to/from the Children collection of the connectors object.
You might of course also want to declare properties for the connector's Stroke, StrokeThickness, etc.

In WinRT C# how do I save an offscreen XAML tree using RenderTargetBitmap?

The following code throws a cryptic System.ArgumentException from the RenderAsync method "Value does not fall within the expected range." If on the other hand my Canvas is part of a visible XAML tree it works. Is it impossible to render some XAML that isn't displayed on screen?
Canvas c = new Canvas();
c.Width = 40;
c.Height = 40;
c.Background = new SolidColorBrush(Color.FromArgb(0xff, 0x80, 0xff, 0x80));
RenderTargetBitmap x = new RenderTargetBitmap();
await x.RenderAsync(c);
I almost thought this answer would work, but no luck, I guess it only applies to WPF: Create WPF element offscreen and render to bitmap
UPDATE:
So far my best idea is to put the Canvas I want to render to into the currently visible page but place it beneath what is normally the root UIElement that fills the screen so it isn't visible to the user:
<Grid>
<Canvas x:Name="HiddenCanvas"/>
<Grid x:Name="mainElement" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
</Grid>
</Grid>
It isn't beautiful but it seems to work. Lets see if anyone can do better
satur9nine's solution to put the rendered UI tree somewhere behind an opaque foreground seems to be the only supported solution. You could also fiddle with the opacity of the parent element to avoid having it showing up. Another option is to render it yourself with Direct2D or use something like the WinRTXamlToolkit.Composition.Render() methods from WinRT XAML Toolkit.
WinRTXamlToolkit.Composition namespace has this extension that works. Just call this method:
await WriteableBitmapRenderExtensions.RenderToPngStream(element);

Changing Display color of PNG with transparency in XAML

I have some PNGs with transparency that I use for buttons in my WPF/C# application.
Right now I have two versions of each PNG, one for normal view and one for hover, each a different color. However, I would really like to just have one single PNG and maybe make everything that's not transparent white (each image is all one color, no detail other than shape.
Would it be possible to then alter the color of each using a SolidColorBrush or similar and create the Normal/Hover versions as a static resource in my XAML?
Something like this:
<Image Key="BtnMenu" Source="Images/Menu.png" Fill="ButtonNormalBrush" />
<Image Key="BtnMenuHover" Source="Images/Menu.png" Fill="ButtonHoverBrush" />
Yeah, I totally made up the "Fill" thing...
But the basic idea is that I have a ResourceDictionary that contains the color scheme that is used throughout the entire application, which makes it so that I can change any of the about 6 colors I use in the application in one place and it updates on every control that references that color... but the one place I cannot do it is those PNGs for the buttons. (Ideally in the future I'll make that ResourceDictionary something that can be loaded in at runtime to make the application have alternate "skins"..but right now the PNGs keep me from doing that).
Edit: BTW, if the solution requires a Converter or something written in code, that's totally fine.
Hmm... If you created a Grid, and put the Image inside that Grid, you could set the Background of the Grid to your fill color.
Edit: Here is some code:
<Button>
<Grid Background="SkyBlue">
<Image Source="img.png" Stretch="None" />
</Grid>
</Button>
There is a solution: http://msdn.microsoft.com/ru-ru/library/ms752364.aspx
You can simply create ImageSource with new Format-object from another ImageSource. Format object specifies color mask for an Image.
You could try to apply a ShaderEffect as the Effect on the hover image or create a markup extension which transforms your image. Another possibility would be to encapsulate such logic in a subclass of Image.

Draw text on a shape in a wpf

Some of you maybe find this question dull but I am still not deeply accustomed to wpf drawing. I want to add formatted text on a Rectangle which moves around on a canvas and I have got a hint to override the UIElement.OnRender method. However I do not know if I should override the canvas class or the Shape class. In any correct case, to what refers the drawingContext parameter of the method as described in the example: http://msdn.microsoft.com/en-us/library/bb613560.aspx#FormattedText_Object ?
Is the text ultimately assigned to the shape or is it a visual temporary effect that cannot move along with the shape on the canvas?
Is there any further effective means of drawing text on a shape?
You can draw Text on top of a Rectangle by placing both controls in a parent container that allows controls to overlap, such as a Grid or a Canvas
<Grid>
<Rectangle Fill="Red" Stroke="Black"
HorizontalAlignement="Stretch" VerticalAlignment="Stretch" />
<Label Content="Test"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
You can then apply whatever formatting you want to the Label, the Rectangle, and you can move the group around by setting the positioning of the Grid
Rachel's answer is correct, although you can extend it a bit, have some UserControl defined as:
And in the codebehind define 1. Label:String DependencyProperty, Shape:UIElement DependencyProperty.
Handle the Shape's change event and call:
private void UpdateShape()
{
grdShapeContainer.Children.Clear();
if(this.Shape != null)
{
grdShapeContainer.Children.Add(this.Shape);
}
}
This way you will be able to make things dynamic.
Regards,
Artak
You might also want to look into ZIndex property which can be set on objects like Grid (<Rectangle Background="Black" Grid.ZIndex = 99 /> for instance would put it overtop other items) which useful for making things like "loading" screens.

Categories

Resources