Draw Circle on Canvas Wpf
WPF excels at creating bully looking applications.
One of the ways you lot can make your application look bully is to add some shapes like circles, triangles and rectangles. However, the shapes in WPF exercise not allow you to add together text (or any content) within the shape, as shapes are non containers.
In a WPF application I am edifice right now, I accept a need to create different shapes and center text within those shapes. The shapes I need are rectangles, circles, ellipses and triangles. The problem is WPF shapes are not containers then yous cannot add any text inside of them, but WPF is flexible enough that there are often several means to work around this. In this article, I volition show yous a few unlike methods of centering text in each of these shapes.
Cartoon an Ellipse/Circle Using a Border
If you wish to put text into an ellipse or a circumvolve, y'all can simulate this using a Edge control and play with the Width, Padding and CornerRadius properties of the Border control. I used the code snippet below to depict text inside an ellipse as shown in Figure ane.

<Edge CornerRadius="50" Width="60" Margin="10" Padding="four" Groundwork="Aquamarine" BorderBrush="Black" BorderThickness="ane"> <TextBlock HorizontalAlignment="Eye" Text="Test" /> </Border>
Yous tin set the width and height of the Border control to create a circle as well. The XAML in the adjacent snippet creates a circumvolve with text in the centre, every bit shown in Figure ii.

<Border CornerRadius="50" Width="60" Height="sixty" Margin="10" Padding="0,20,0,0" Groundwork="Aquamarine" BorderBrush="Blackness" BorderThickness="1"> <TextBlock HorizontalAlignment="Centre" Text="Exam" /> </Edge>
Draw a Triangle Using a Visual Brush
To create a triangle shape in WPF you utilise a Polygon control. If you lot call up your high schoolhouse math, a Polygon is a series of continued lines that have the same offset and end point. The XAML beneath creates a triangle; however, there is no text in information technology considering a Polygon is not a container.
<Polygon Points="25,0 5,30 45,30" Fill="LightBlue" Stroke="Black" StrokeThickness="2" />
To add together text similar that shown in Figure iii, you need to apply the Polygon control as the groundwork of a TextBlock control. The XAML shown in Listing one is used to create Figure 3.

2 fundamental things make this XAML work. Offset, yous use the VisualBrush object of the Background of the TextBlock object to give y'all a place to put the Polygon control. Second, depending on the text that you fill into the TextBlock command, and the width and peak of the TextBlock control, you will need to play with the Padding property to align the text to the right location. Have the higher up XAML and put it in a new window and then adjust the height, width and text values. You will see that you need to adjust the Padding belongings to make the text fall into the correct location within the Polygon.
Listing 2 shows another instance of a Visual Brush, this time using an Ellipse control. Figure four shows the results of the XAML in List 2.

Notice the Padding attribute is dissimilar than when using the Polygon control. You will need to make minor adjustments based on the shape that you are using and the peak and width of the control, and the text you are putting into the TextBlock.
Position a Shape on a Canvas
Using a Visual Brush inside a TextBlock control works, only it is not very re-usable code. The ultimate goal of this article is to show you lot how to move all of this code into one user control that y'all can use over and over over again. Before you can learn that technique, you first need to larn to utilize a Sail, a Shape, a TextBlock and MultiBinding converters.
You employ a WPF Sheet control to position child controls at a specified indicate on the Canvas. I created Figure 5 by placing a shape (yous tin use any command) at a certain point by setting the attached properties "Canvass.Summit" and "Canvas.Left". In Figure 5 yous can come across that the circumvolve is positioned xx points below the top of the Canvas and 40 points to the right of the Canvas' leftmost border. I used the XAML below to create Effigy 5.

<Canvass Name="cnvMain" Width="80" Height="eighty"> <Ellipse Sheet.Top="20" Canvas.Left="40" Width="40" Pinnacle="twoscore" Fill="Gray" /> </Sail>
Place a Shape inside a Sheet
Most of the fourth dimension, you lot want a shape to take up the same amount of width and height equally the Canvas. So, y'all tin simply set the Width and Acme properties of both the Canvas command and the Shape control to exist exactly the aforementioned. Since the Shape command is the child within the Canvass, it will fill upward the whole Canvas. Note that you do not need to specify the Sheet.Top and Sail.Left as the default for these is null (0) for any child control placed in a Canvas as shown in the following XAML.
<Sail Name="cnvMain" Width="lxxx" Tiptop="80"> <Ellipse Width="80" Height="80" Fill="Grey" /> </Canvas>
Bind Ellipse Width and Elevation to Canvas
The problem with the in a higher place XAML is that if you wish to change the width and the height of the Sheet and you want the shape to be the verbal same height, you lot need to change iv numbers. Instead of hard-coding the numbers on the Shape control, you can take advantage of the element-to-element bounden features of WPF. Below is an example of binding the Width and Elevation of the ellipsis to the Width and Peak of the Canvas. The XAML below will produce the circle shown in Figure vi.

<Canvas Name="cnvMain" Width="80" Tiptop="lxxx"> <Ellipse Width="{Binding ElementName=cnvMain, Path=ActualWidth}" Height="{Binding ElementName=cnvMain, Path=ActualHeight}" Fill="Gray" /> </Canvas>
Using a MultiBinding Converter
Now that yous accept a Shape within a Sail y'all can place a TextBlock in the centre of the Sail to brandish text in the middle of that Shape. To center a TextBlock in the middle of a Canvas yous demand to take the width of the Canvas and decrease the width of the TextBlock, and then split this by 2 to become the value for the Left property. You use the same adding for height to get the Top property of where to position the TextBlock in relation to the top of the Canvas.
It would exist actually user-friendly if you could use an expression in a WPF bounden since you lot could and so perform this calculation, but y'all can't. So, instead, you lot demand to pass the width of the Canvas and the width of the TextBlock to some code yous write, and too the superlative of the Canvas and TextBlock. This is where a MultiBinding converter comes in very handy.
The upshot of the MultiBinding converters, shown in Listing three, is to gear up the "Sheet.Left" and "Canvas.Top" backdrop of the TextBlock control. If you are familiar with a normal WPFbinding markup extension, you understand how a converter form is used to catechumen a unmarried input value and produce a single output value that you lot assign to a holding. A MultiBinding converter allows you to laissez passer more than one value to a converter course. Observe the "Converter={…}" attribute uses a StaticResource called Midvalue. This static resource is defined in the Window.Resources section of this window equally follows:
<Window.Resources> <src:MidpointValueConverter x:Key="MidValue" /> </Window.Resources>
The MidPointValueConverter grade implements the IMultiValueConverter interface. This interface defines the Convert and ConvertBack methods but like a normal value converter method. It is your job to write the code to take the multiple inputs that are passed to the "values" parameter to the Convert method and return a single value that can be used to set the Left property. List 4 shows the MidPointValueConverter grade.
In the MidPointValueConverter grade you grab the 2 values passed in, which are the total width/tiptop of the Canvas, and and then the total width/superlative of the TextBlock control. You lot can and then subtract those 2 values and split up by 2 to get the location of either the Left or the Top belongings.
Find that you can also pass in an "extra" value in the "parameter" parameter. You tin can use this extra value if y'all want to motion the TextBlock control down or to the right depending on the shape you use. For example, if y'all are using a triangle with the point of the triangle at the acme, you lot might want to move the text a picayune lower into the widest function of the triangle instead of right in the eye of the triangle. Or, if you lot accept a triangle where the indicate is to the right, then you might want to move the text a piddling over to the left. You fix this "extra" parameter as the ConverterParameter attribute on the MultiBindingXAML element as shown in List five.
Figure 7 shows the results of the rectangle with text in it, and the effect of using a polygon with the ConverterParameter set.

Creating a User Control for Hosting Shapes
So, up to this point you have now learned how to create shapes and eye text inside those shapes using a couple of different methods. Now information technology is time to wrap upward all this functionality into a nice, re-usable user control. In Effigy 8 yous see a couple of shapes that were created using a user control chosen "ucShape". The first one draws a circumvolve with the name "Paul" in information technology while the second i is a triangle.

Listing six shows the XAML used to create the circle in Figure 8. Notice each of the properties y'all can set on the user command. You can set the text to display on the shape using the TextToDisplay belongings. You use the Shape property to specify which type of shape y'all wish to display. Y'all can apply six unlike shapes with this user command; Rectangle, Square, Triangle, InvertedTriangle, Ellipse and Circumvolve. Other properties that y'all tin can ready include the color of the shape, the text, and the acme and width of the shape.
Listing 7 shows the XAML code that draws the triangle shown in Figure 8. I've sent the ShapeToCreate property in this sample to "Triangle". Notice the additional backdrop HeightOffset and WidthOffset. Normally the text is centered directly in the middle of the shape but with a triangle you will want to move the text to the fattest role of the triangle. These two additional properties suit the text upwardly, down, left or right.
Build a Shape User Control
To create your own shape user control yous add together a user command named ucShape to your projection and add together each of the properties shown in List seven. You volition need to set upwardly an enumeration for each shape as seen in the code below.
public enum ShapeEnums { Rectangle, Square, Triangle, InvertedTriangle, Ellipse, Circle }
Y'all create the appropriate property become and set statements within the user command for each of the properties in Listing 7. I am not going to listing the code for those here as I presume you know how to create normal properties. Yous can get the complete source lawmaking (in C# or VB) for this user control by downloading the sample code at www.pdsa.com/downloads.
The User Control XAML
Listing eight is the consummate XAML for your ucShape user control. A Canvas control is the container control for the entire user control. Y'all'll use the Canvas command to center the text at a specific betoken on the command. Notice that you lot do not employ a shape control in the user control. The code will create the shape at run fourth dimension by examining the ShapeToCreate belongings and adding the appropriate shape onto the Canvass at the appropriate location.
Notice the binding extensions on the Canvas control to the ActualWidth and ActualHeight properties of the user command. When you prepare the Width and Height properties on the user control these values will be used to prepare the Canvas to the same height.
The TextBlock control is contained within the Canvas command, but no other properties are set on this control. The backdrop such as where to place the TextBlock command on the Canvas, the Foreground color, the text, etc., will be ready dynamically at run time based on the properties you assault the user control.
Loading the User Control
When an instance of the ucShape user command is loaded, the code creates the shape based on the ShapeToCreate property. The advisable backdrop on the TextBlock control such as the Text, the Top and Left will also be prepare at this fourth dimension. The Top and Left properties of the TextBlock will exist set through the MultiBinding converter created in code this fourth dimension as opposed to in the XAML.
List 9 shows the lawmaking for the Loaded event on the ucShape user control. This upshot procedure calls a method named CreateShape which is where the logic for creating each of the shapes is located. If a valid shape is returned from the CreateShape method, and so that shape is inserted as the first control on the Sheet control.
The Loaded event procedure sets the Foreground property on the TextBlock control from the TextColor property gear up when the user control was alleged. Finally, the MultiBinding converter for the Left and Elevation properties on the TextBlock control are created by calling the SetWidthMultiBinding and SetHeightMultiBinding. You will encounter this code a lilliputian later in this article.
The CreateShape Method
The CreateShape method (Listing 10) is fairly directly-frontward WPF code. It contains a switch statement that checks the ShapeToCreate belongings. Based on that property, the appropriate shape is created and appropriate Width and Height properties on the shape are spring to the Width and Summit properties on the Canvas command.
Create a MultiBinding in Code
In Listing v you saw how to utilize a MultiBinding converter to pass in 2 parameters from XAML and go a unmarried value returned. Since you have moved all of the lawmaking into the user control, you will now create these MultiBinding converters in code as well. Listing 11 shows the lawmaking for calculating the Left and Acme backdrop for the TextBlock. Yes, you could take still created the MultiBinding converters in XAML, but I thought it would be expert to show y'all how to perform the same matter using WPF code.
Summary
In this article, y'all learned how create text centered on a shape using a few unlike methods. Information technology just goes to prove that there are always several methods to accomplish the same matter in WPF. For a quick and dirty approach, using a VisualBrush within a TextBlock works quite well. Using a user command is the best approach when you want to re-apply the shape and text over and over again. Yous can place the user control and all the associated code into a DLL to reuse in many applications.
List i: Place Text in a Triangle using a Visual Brush
<TextBlock Text="Test" Width="l" Height="50" Padding="13,28,0,0"> <TextBlock.Background> <VisualBrush> <VisualBrush.Visual> <Polygon Points="25,0 5,30 45,30" Make full="LightBlue" Stroke="Black" StrokeThickness="two" /> </VisualBrush.Visual> </VisualBrush> </TextBlock.Background> </TextBlock>
List 2: Place Text in an Ellipse using a Visual Castor
<TextBlock Text="Test" Height="twoscore" Width="40" Padding="8,10,0,0"> <TextBlock.Background> <VisualBrush> <VisualBrush.Visual> <Ellipse Top="xx" Width="xx" Fill="LightBlue" /> </VisualBrush.Visual> </VisualBrush> </TextBlock.Background> </TextBlock>
Listing 3: Use MultiBinding converters to perform calculations and assign the result to properties
<Canvas Name="cnvMain" Width="40" Summit="twoscore"> <Rectangle Name="rectSize" Fill="Bluish" Width="{Binding ElementName=cnvMain, Path=ActualWidth}" Height="{Binding ElementName=cnvMain, Path=ActualHeight}" Stroke="Black" StrokeThickness="2" /> <TextBlock Proper noun="tbSize" Foreground="White" Text="Exam"> <Sheet.Left> <MultiBinding Converter="{StaticResource MidValue}"> <Bounden ElementName="cnvMain" Path="ActualWidth" /> <Binding ElementName="tbSize" Path="ActualWidth" /> </MultiBinding> </Canvas.Left> <Canvas.Top> <MultiBinding Converter="{StaticResource MidValue}"> <Bounden ElementName="cnvMain" Path="ActualHeight" /> <Binding ElementName="tbSize" Path="ActualHeight" /> </MultiBinding> </Canvass.Top> </TextBlock> </Canvas>
Listing 4: The MidPointValueConverter class takes multiple inputs to produce a single output
C# using System; using System.Globalization; using Arrangement.Windows.Data; public form MidpointValueConverter : IMultiValueConverter { #region Catechumen/ConvertBack Methods public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { double commencement = 0; double totalMeasure = 0; double controlMeasure = 0; // Make certain enough "values" were passed if (values == nil || values.Length < 2) { throw new ArgumentException("The MidpointValueConverter class requires 2 double values to exist passed to it. First pass the total measure of the outside command, and then the total measure of the command to exist placed inside the exterior control.", "values"); } // Go the total width/summit totalMeasure = (double)values[0]; // Get the width/height of the control controlMeasure = (double)values[ane]; // check for any offset to the width/acme if (parameter != null) offset = Arrangement.Convert.ToDouble(parameter); return (object)(((totalMeasure - controlMeasure) / 2) + outset); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo civilization) { throw new NotImplementedException(); }
Post a Comment for "Draw Circle on Canvas Wpf"