Articles on this Page
- 04/15/10--06:10:_Moving From WinForms to WPF
- 04/16/10--16:08:_Beginning Sivlerlight –...
- 04/17/10--23:33:_Beginning Silverlight –...
- 04/19/10--12:02:_WPF: Accessing Resources...
- 04/23/10--05:34:_Video Training With...
- 04/23/10--12:46:_VB vs. C# - my opinion
- 04/23/10--16:27:_Beginning Silverlight –...
- 04/24/10--05:46:_Dynamically Read,...
- 04/24/10--15:10:_Beginning Silverlight –...
- 04/25/10--01:21:_Beginning Silverlight –...
- 04/29/10--05:06:_‘A data source instance...
- 05/02/10--01:22:_Silverlight Brush Examples
- 05/02/10--01:28:_Beginning Silverlight -...
- 05/02/10--01:51:_Beginning Silverlight -...
- 05/07/10--15:42:_Beginning Silverlight -...
- 05/07/10--15:57:_Silverlight Transform...
- 05/08/10--20:42:_Beginning Silverlight -...
- 05/08/10--21:12:_Silverlight...
- 05/15/10--15:57:_Routing with ASP.Net 4.0...
- 05/18/10--19:53:_Beginning Silverlight -...
More Channels
- Feb 23: Last.fm Events
- Nov 25: GETAWAY TO NOWHERE.... Hahaha!
- Nov 25: s0me0ne who can lie to...
- Nov 25: MTC Academy Davao's Site
- Nov 25: Pirates / Heroes
- Feb 4: Random Numbers
- Nov 25: Meg's Site
- Nov 25: shin chan's Site
- Nov 25: theY calL iT lOve,,I calL iT...
- Nov 25: mspplanetz
- Nov 25: [ O Y A ]
- Nov 25: "Let the light cease."
- Nov 25: Princess Ivory World
- Nov 25: RJ's Site
- Nov 25: Michelle-McCool.org » Your Top...
- Nov 25: Saremo mica tutte Anime in...
- Nov 25: I @M MILLAH
- Jan 28: وبلاگ گروه...
- Nov 25: پروانه ی بی خویشی...
- Nov 25: Fotoblog moina
- Nov 25: thanongsak's Site
- Dec 18: Comments for thoughts shared,...
- Nov 25: Nyquist Art + Logic
- Nov 25: GyaO!ストア - 推しV -...
- Nov 25: ...
- Feb 22:
- Nov 25: Psst moet je horen!
- Nov 25: Fotoblog punksnotdead
- Nov 25: スナック リラックス |...
- Nov 25: Rich club » Non classé
- Feb 6: Scienceline.ro - ScienceLine.ro
- Jan 7: MegaMagasin
- Nov 25: Merzylicious
- Feb 19: وبگاه محمد حسین...
- Nov 25: But I can keep my eyes open but...
- Nov 25: Mijush...xP - Komentáře
- Nov 25:
- Nov 25: nEw set of liFe = a neW me
- Nov 25: Вечером на кухне
- Nov 25: Max Art
- Nov 25: Mobiles News
- Dec 8: دکترمحسن مدرسی...
- Feb 17: RBV - Články
- Feb 20: Money.ro - Stiri - MARKETS
- Feb 13: يك جرعه غزل
- Nov 25: Ultimate Source For Telugu Songs...
- Nov 25: carpe diem~ (INACTIVE)
- Nov 25: Nurmal's Site
- Nov 25: Fotoblog ola0208
- Nov 25: I ♥ Twilight - Články
|
|
Are you the publisher? Claim this channel |
|
Channel Description:
Latest Articles in this Channel:
- 04/15/10--06:10: Moving From WinForms to WPF (chan 2127976)
- Alignment
- Button
- Code-behind
- Event Handling
- Grid
- Label
- Margins
- Nested content
- Properties Pane
- Reloading Message
- Resolution Independence
- TextBlock
- TextBox
- Window Title
- XAML pane
- 04/16/10--16:08: Beginning Sivlerlight – Brushes (chan 2127976)
- 04/17/10--23:33: Beginning Silverlight – Brushes Part 2 (chan 2127976)
- 04/19/10--12:02: WPF: Accessing Resources From An External Project (chan 2127976)
- 04/23/10--05:34: Video Training With LearnDevNow (chan 2127976)
- SharePoint
- SQL Server and BI
- Visual Basic Web
- Visual Basic Windows
- C# Web
- C# Windows
- 04/23/10--12:46: VB vs. C# - my opinion (chan 2127976)
-
Assign 7 to a.
-
Perform the logic in the "if" block.
- 04/23/10--16:27: Beginning Silverlight – Brushes 3 (chan 2127976)
- 04/24/10--05:46: Dynamically Read, Compile, and Run Source Code From a Text File (chan 2127976)
- Read the code from the file.
- Create an instance of a VB.NET compiler
- Create compiler parameters and pass them to the compiler
- Compile the code
- Check for errors
- Create an instance of the class containing the code
- Create arguments to pass to our compiled code
- Execute the code and see results
- 04/24/10--15:10: Beginning Silverlight – RotateTransform (chan 2127976)
- 04/25/10--01:21: Beginning Silverlight – SkewTransform (chan 2127976)
- 04/29/10--05:06: ‘A data source instance has not been supplied for the data source’ error (chan 2127976)
- 05/02/10--01:22: Silverlight Brush Examples (chan 2127976)
- 05/02/10--01:28: Beginning Silverlight - ScaleTransform (chan 2127976)
- 05/02/10--01:51: Beginning Silverlight - TranslateTransform (chan 2127976)
- 05/07/10--15:42: Beginning Silverlight - TransformGroup (chan 2127976)
- 05/07/10--15:57: Silverlight Transform Examples (chan 2127976)
- 05/08/10--20:42: Beginning Silverlight - PlaneProjection (chan 2127976)
- 05/08/10--21:12: Silverlight PlaneProjection Example (chan 2127976)
- 05/15/10--15:57: Routing with ASP.Net 4.0 - SEO - real simple (chan 2127976)
-
It needs a routing key.
-
It needs the mapping path. E.g. the path of the public URL you provide to the end users that maps to the physical path of the file that will handle the request.
-
It *needs* a Route value dictionary, where you define the parameter names, and their default values
-
Optionally, you can add an additional RouteValueDictionary object to list constraints for those values.
- 05/18/10--19:53: Beginning Silverlight - Element Binding (chan 2127976)
I’ve written lots of blog posts about WPF and in most cases the selection of topics has been a bit random. Essentially, if it interests me at the time I’d write about it. The problem with that approach is that it might assume a more basic grasp of WPF than many readers have.
In a recent post on VB City, someone said (in a discussion about WPF): “I don't know where to start and a WPF primer would be good”. Not knowing where to start is probably a common problem, so I plan to write a few blog posts that will take a WPF 101 approach. I’ll still be writing the higher level blogs in between times, but hopefully this series will be useful to those who are familiar with WinForms and want to see the specific differences between WinForms and WPF.
To make the blogs’ content accessible to the widest range of readers, I’ll base the samples on the VB Express version. Today we’re still at VB2008, but VB2010 will be along in a few weeks and I’ll switch to that when it happens. I’ll also try and flag up any important differences between the 2008 and 2010 versions.
So let’s get started.
Create a new WPF project
Start a new project and select the WPF Application template:
I’ve named it WPF101_1.
Check out the IDE
The view in the IDE is similar to the one for WinForms, but there are some obvious differences.
The first major change from WinForms is the way that the design area is split. The top half still shows the design view of the ‘Form’ (now a Window in WPF, but very similar in role to a Form). Below that, there’s the XAML pane.
XAML is a version of XML that you can use in WPF to design elements. We’ll be looking at XAML in much more detail as we progress, but for now remember that you don’t have to be an expert in XAML to be able to create some very useful and good WPF applications. In fact you could create everything using Visual Basic, although this isn’t the most efficient way of doing it.
The list of items in the Solution Explorer is also slightly different. There are new file types listed – specifically by default Application.xaml and Window1.xaml. Both those XAML files have a plus sign next to them. When you click on the plus sign, a second file with the extension of xaml.vb appears. In general, the role of the XAML files is to hold the markup that represents the look of the elements in the project. The xaml.vb file, which is usually referred to as the code-behind file, generally deals with the behaviour. Their roles are a lot more flexible than that, but it’s a reasonable way of thinking of them at this early stage.
The Toolbox at the left hand side of the IDE is similar to the WinForms one.
Many of the names of the controls are the same in both WinForms and WPF. This is both a good and bad thing. It’s good because you’ll be familiar with them. It’s bad because there are often differences that will catch you out if you’re not aware of them.
Create a Hello World! Window
1. Add a Button to the Window
As a start point, I’ll create the canonical Hello World! app. From the ‘Common’ tab of the Toolbox, select and drag a Button on to the surface of the Window. A key difference between WPF and Winforms when you do this is that you will see that some additional XAML is added to the XAML pane below the Designer.
Your version won’t be exactly the same. The Margin values, for instance, are likely to be different. Also, I’ve split up the original into three lines just to reduce the width of the screenshot.
The XAML markup you see there between the opening and closing tags creates an instance of a Button. Here’s the Button in the Design pane.
Looking at the things you see in the Design and XAML panes, these bring up various WPF specific points :
Nested Content There are two blue bars at the left and top of the Window, each with a number in them. To understand what these represent, you need to look back at the XAML that was automatically created for this Window. On line 5 you see there is an opening tag for a Grid. On Line 9, there is a closing tag for this Grid. Whenever you create a new Window in the IDE, a Grid will be placed inside the Window in this way. It’s placed there is to act as a container for the remaining content.
One of the features of WPF is that many of the visual elements can only contain a single child. Now, although you may think it’s bizarre at this stage, a WPF Window is one of the elements that can contain only one child element. If that were literally true, the options for useful Windows and user-friendly applications would be very limited. It is true, but the get out clause is that each child element may content sub-elements. And each sub-element may contain its own children and so on. Therefore this isn’t really a limitation at all. We’ll look at why WPF layout is structured in this way later.
In the example so far, the Window has a child element of a Grid and the Grid has a Button as its child.
Grid Markers Going back to the blue bars, these mark the outside edge of the Grid. The values represent the height and width of the Grid. You will see in a later blog post how you can the Grid’s blue bars to add columns and rows to a grid.
Resolution Independence The Button has been given a fixed Height value of 23 and a Width of 75 pixels. You should note that these aren’t the standard screen pixels that you are used to in Winforms. They are what is known as ‘device independent units’. Confusingly, they are often referred to as ‘device independent pixels’, which almost inevitably results in them sometimes being referred to as just plain old ‘pixels’. But they are different from the pixels of your Winforms applications.
The device independent pixel of WPF respects the Dots Per Inch (DPI) setting of the system it is using. What this means in reality is that if you create your WPF button and deploy the application to a system that has a higher DPI setting, WPF will use more than ‘your’ 23 and 75 pixels to render it. The effect of this is that the button will be as crisp on a machine with a different DPI setting as it is on yours. You don’t get that scrunching up of the elements that you often see in this situation.
What happens is that WPF’s rendering engine makes full use of the available pixels on the deployed system. So if the machine the application is deployed on has a System DPI of, say, 120 then WPF would use 29 of those higher density pixels for the height and 94 for the width (approximately), rather than the original 23 and 75. This is different from the blocky “fill in the extra pixels and get a jaggy result” effect that you will have seen elsewhere. Because WPF renders everything on screen using vector graphics, you simply get a higher density version of the original.
Margins The XAML markup shows the Margin property for the Button. The four values represent the distance in device independent units that this button will always be from the edges of its parent. In the current example, it is 48 units from the left edge of the Grid and 40 units from the top. If you drag the button around in the Design pane, then let go, you’ll see that the values of the Margin property settings will change to reflect where you’ve left the Button. The four values in the Margin setting represent Left, Top, Right, Bottom – always in that order.
Alignment You’ll also have noticed the two arrow pointing from the Button to the edge of the Grid. These signify that the Button is horizontally aligned to the left and vertically aligned to the top. This is also confirmed in the properties shown in the XAML. You can think of this as being the same as the Anchor properties in Winforms. WPF however offers much more subtle options than just plain anchoring.
if you did try dragging the button around in the Design pane, you’ll probably have found that, quite confusingly, not only do the top and left margin values change, but you might also see either the HorizontalAlignment, the VerticalAlignment, or both of them, disappear from the XAML. The reason for this is that WPF has a very sophisticated layout toolset that you can use directly in the Design pane. (You can of course manually make changes to the XAML, but because this is Winforms –> WPF, I’m going to try and use minimal hand coding of XAML.)
Looking at my original screenshot of the Window, you’ll see that at the right and bottom of the Button there is a small circle. Hover over the one at the right and you’ll see a hand icon appear. It can be a bit fiddly, so make sure you have the hand, not the double-headed arrow. If necessary, use the excellent Zoom scaling tool in the top left hand corner of the Design pane to increase the size of the display.
Now, click on the circle and three things will happen. The circle will go and be replaced by another arrow, this one pointing to the right hand edge of the grid. The third value in the Margin property down in the XAML pane will change from to a new value. Finally, the HorizontalAlignment property will disappear from the XAML.
The result of this change will be that if you run the project and change the size of the Window, the Button’s width will change so that it is always the same distance from the left and right edges. So at this point you have three-way anchoring.
Vertically, there will be no change if you alter the size of the Window, because the HorizontalAlignment is still set to Top and there is a constant Margin of 39 units between the top of the Button and the top of the Grid. Obviously, if you click on the circle at the bottom of the button, this will make a similar change to the vertical settings.
If you click on any of the arrows, they will change to circles. This is a feature you need to experiment with in order to become totally familiar with it.
Button Content You’ll see the word ‘Button’ located between the opening and closing tags of the Button element markup. The same word also appears on the face of the button in the Design pane. In a similar way to how Winforms assigns a default Text property of ‘Button1’ to a button, WPF assigns a default Content property of a string containing the word ‘Button’. Note that it’s not a Text property, as in Winforms, even though in this case it does happen to be text. In WPF, Content is everything. A WPF button can have almost any content. The limitations of text and an image are gone. If you remember my explanation above of nested content, this applies equally to buttons. So a button can contain layers of nested content. I’ll be covering the possibilities of this later, but for now just keep in mind that it’s Content and not Text.
WPF controls have default properties and the default property of a button is Content. Because of this, the XAML is displayed in the way you first saw above. I think the IDE maybe does you a disservice here by doing this. Another way of more specifically identifying the Content is to include its property value within the opening tag:
So, even with something as basic as a button, you’ll see that there are already important differences between Winforms and WPF.
2. Add a TextBlock to the Window
Expand the ‘Controls’ tab in the Toolbox and scroll down until you reach the TextBlock. Drag one on to the Window’s surface.
Again you will see the alignment arrows and, as before with the button, you change these settings.
The default Property of a TextBlock is the Text property. When first created, the TextBlock is empty. You can enter text for the TextBlock either by placing it between the opening and closing tags or by specifically assigning a value to the Text property.
<TextBlock Height="21" Margin="39,0,62,38" Name="TextBlock1" VerticalAlignment="Bottom" Text="This is a TextBlock" />
For the sake of completeness, I should tell you that it is possible to include other sub-elements inside a TextBlock. And these don’t even have to be text. That said, there are many better options for cases where you want to mix text and other graphical elements, so my advice is to stick to using the TextBlock for plain text. Well, not plain text – WPF offers you a lot of options for enhancing the look and style of text. I’ll cover these choices later.
The WPF TextBlock is a Read Only control. If you want to take text input from a user, a TextBox, similar to the WinForms one, is available. You may have noticed that there is a Label element available in the Toolbox. I could have used this and it would have worked fine, but I chose the TextBlock because for most purposes in WPF apps it’s a better option.
3. Add the Button’s Event Handling Code
In many cases, you can do what you probably do with a Winforms button in order to create and access its Click event. You double-click on the button in the Design pane. This will automatically create the event handler code which include the familiar ‘Handles’ clause at the end of the signature line. In this example, ‘Handles Button1.Click’. It also brings up the xaml.vb code-behind file in the IDE to allow you to start adding code.
There is also an alternative. Back in the XAML for the Button, you can add a Click property inside the Button’s opening tag. When type in ‘Click=’ you will get a context menu:
In the above screenshot, the menu only contains the one choice of New Event Handler. If the code-behind file contains other procedures, these will also be listed as choices. When you double-click on the New Event handler choice an event handler will be created for you in the code-behind. This procedure won’t include the Handles clause. The Handles clause isn’t needed for our Button1 instance, because it is already wired up via the Click property in the XAML.
As for the VB code in the event handler, this will be:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
TextBlock1.Text = "Hello World!"
End Sub
Apart from the new WPF control, the syntax will be familiar, i.e. assigning a value to the Text property. The code differences between Winforms and WPF unfortunately won’t always be this simple, but I’ll try and cover many of the Gotchas as we come to them.
Change the Heading of the Window
In Windows Forms, you set the Text property of a Form to change what is shown as its heading. In WPF, the Window has a Title property that does the same thing. You’ll find this within the opening tag of the Window in the XAML pane.
You can edit it there or you can select the Window in either the Design or XAML panes and then change the value of the Title property in the Properties pane.
Run the Project
When you run the project and click on the Button, the event handler in the code-behind will populate the TextBlock with the Hello World string.
Other Points
Reloading. You’ll often find that you see a gold bar at the top of the Design pane that says “An assembly or related document has been updated which requires the designer to be reloaded. Click here to reload”. You need to click on this before continuing. This message will appear whenever you make a change (usually in the code-behind or elsewhere in the project) and the layout engine needs to figure out how that affects what it’s going to show you as a result of the change.
Properties Pane. The Properties pane is available to you in the same way as in Winforms. You can click on an element either in the Design pane or the XAML pane and its properties will appear in the Properties pane, where you can view or edit them. So you don’t even need to edit the XAML in most cases if you’re more comfortable using the Properties pane.
Summary
In this first article, you’ve seen some of the differences between WPF and Windows Forms. There’s still an awfully long way to go and many differences to learn about, but at least we’ve made a start.
Some coverage of the following topics has been included:
Brushes are what you use to give color to your applications.
There are five types of brushes that you can use for colour in a Silverlight application. There is the SolidColorBrush, LinearGradientBrush, RadialGradientBrush, ImageBrush and VideoBrush.
In this first part of a three part look into brushes for Silverlight, I am going to look at the SolidColorBrush and LinearGradientBrush.
For this example I have created a silverlight project that has a border in the middle of a grid.
So the border can be seen I have set the background to red.
1. The SolidColorBrush.
By default when you set the colour property of a silverlight element inline as I have done above, you are actually creating a solidcolorbrush.
*Note:
For the purpose of this post I will be using the property-element syntax of XAML to highlight the different approaches to using the different types of brushes as the background for the border. To use this type of syntax for complex properties of an element, you would enclose the XAML for the property between Partent.PropertyName opening and closing tags. This type of syntax may not always be the best way to define elements.
When working with a solidcolorbrush you have a few options when it comes to setting the colour you want. You could choose from one of the 141 pre-named colurs, which includes Transparent, from the pop windows after typing the word Color in the XAML.
If I were to select Red from the list, the XAML below would create the same effect as the XAML that I started this post with.
1a. Defining solid colours.
You are not limited to the pre-named colours by any means. The colour can be defined by several methods.
- Using a pre-names colour.
- Use 3 digit Hexadecimal value where the first digit represents R value, the middle digit represents G value and the third digit represents B value.
- Use 4 digit Hexadecimal value where the first digit represents A value, the second digit represents R value, the third digit represents G value and the fourth digit represents the B value.
- Use 6 digit Hexadecimal value where the first two digits represent R value, middle two digits represent G value and the last two digits represent B value.
- Use 8 digit Hexadecimal value where the first two digits represent A value, second and third digits represent R value, fourth and fifth digits represent G value and the last two digits represent B value.
The following XAML shows five different ways to get the same result.
2. Create a GradientBrush.
So having taken a look at a brush that makes use of one colour, what do you do if you want something more interesting than a single colour as the background? Something perhaps like the image below.
The answer is easy. If you want to have more than one colour in your brush you make use of one of the two gradient brushes available to you.
2a. The LinearGradientBrush.
A lineargradientbrush is a brush that contains two or more colours where the first colour starts out as a solid then changes uniformly before finishing as solid in the second colour along a straight line. If there are more than two colours in the gradient the same rule of solid, mix solid applies. If you have three colours then you would end up with a gradient of solid, mix, solid, mix, solid.
By default when define a lineargradientbrush
the gradient follows a diagonal line, the gradient axis, which starts at the top left corner of the element the brush is applied to and ends at the lower right corner. The starting and ending points are defined by a set of coordinates where the top left corner is 0,0 and the bottom right corner is 1,1.
While you don’t need to add the StartPoint and EndPoint when you define the brush, I find it a good habit to get into.
2a_a Changing start and end points.
By changing the startpoint and endpoint of your brush when you define it you control the gradient brush is painted onto the element it is being applied to. You can set your start and end points anywhere to any value from 0 to 1 along either side of your element.
Changing the endpoint of your brush to the top right corner of your element,
gives you a vertical gradient spread over your element.
Likewise changing the endpoint of the brush to the bottom left corner of the element,
gives you a horizontal gradient.
You are also not limited to whole numbers for either coordinate of your start or end points. The value of the coordinate is a type of double so you can use decimals.
By setting the startpoint to 0.5,0 I have moved the red so it is solid further along the top of the border. It is hard to see in the screen shot, but you should be able to see that there is now more solid red along the top of the border and the gradient looks like it is on a more horizontal angle.
Another thing you are not limited to with the startpoint and endpoint of the brush is positive numbers.
You can use negative numbers to move one, or both, solid colours off the element you are painting.
2a_b Adding Colours to the brush.
The colours that you have in the brush are defined by adding a GradientStop to the GradientStops collection. If you are defining your brush in XAML you don’t need to add the opening and closing tags for the collection of gradientstops you can just add the definition of the gradientstop itself.
Each gradientstop has two properties a Color and Offset. The color is pretty much self-explanatory it sets the colour of the stop. You can define the colour using any of the methods that I described above. The offset is where the stop, or the solid colour, is positioned along the gradient. The offset takes a value from 0, the beginning of the gradient, and 1at the end of the gradient.
The following XAML adds two solid colours to the collection of gradientstops. Red is a solid colour at the start of the gradient and yellow is a solid at the end of the gradient.
Between the two solid colours the colours are mixed, or interpolated, evenly giving the result in the following screen shot.
To add more colours to the gradient you just need to define another gradientstop to the collection.
Changing the offset of the yellow to .5 moves it to the middle of the gradient to blend with both the red and blue.
While having the ability to have several colours in a brush if you use too many it can get difficult to manage to offset properties of each gradientstop so some care should be taken.
In the next post I will take a look at the radialgradientbrush.
This is part two of a look into the different types of brushes that you can use with Silverlight.
In part one I took a look at the SolidColorBrush and the LinearGradientBrush.
In this post the RadialGradientBrush. I was also going to take a look at the ImageBrush and the VideoBrush but due to the length of this post I will do a Brushes Part 3.
1. The RadialGradientBrush.
You would use the radialgradientbrush in much the same manner that you would a lineargradientbrush. You define the brush in XAML
then add a collection of gradientstops, each gradientstop defines a colour and where the colour starts in the gradient.
The first colour starts at the center point, or focal point, of the brush and mixes, or interpolates, with the other colour of the brush until the second colour becomes solid at the end point, or circle point, of the gradient.
As you can see in the screen shot below, the gradient starts red at the center point of the circle and mixes evenly with yellow until it becomes solid yellow where the white circle is.
1a. The Offset property of a GradientStop.
The offset property of a gradientstop is handles slightly differently in a radialgradient as opposed to a lineargradient. As mentioned in part 1, the offset of a gradientstop follow a gradient axis which runs from the top left corner of the element being painted to the bottom right corner. With a radialgradientbrush a transparent circle, for lack of a better description, is placed over the element being painted and the gradient starts at the center of the circle, 0 in the image below, and go to the outer edge of the circle. Offset values can be either whole or decimal numbers, of any value, both positive and negative.
1b. Setting the Center Property.
The center property is defined by a set of coordinates. By default when you define a radialgradientbrush the center property, even if you don’t add a value in your XAML is 0.5,0.5. This value places the center point in the exact middle of the element you are painting with the brush. This point is also the center of the outer circle of the brush.
The center property coordinates are take a value based on the top left corner of the element being painted being 0,0 and moving outward and downward until reaching the bottom right corner which would be 1,1.
By changing the value of the center property, you can move where the circle for the brush is over the element.
In the XAML below I have set the center of the brush to be half way down the left side of the element.
You can see in the screen shot below that the circle now is half in and half outside the bounds of the border with the center of the circle on in the middle of the left side.
You will note that even though the center of the circle is down the left side of the border, the center of the gradient isn’t. You can see that it still is in the center of the border right at the edge of the circle.
1c. The GradientOrigin Property.
The gradientorigin is automatically placed at 0.5,0.5 unless specifically set then the brush is defined.
This places the first color, or the color with the offset property of 0, in the center of the gradient circle.
The coordinates that the gradientorigin follow the same lines as the coordinate system used to place the center property starting at 0,0 in the upper left corner of the element.
One thing to keep in mind when setting the gradientorigin is to remember that, even the element you are painting with the brush may be square or rectangular, this brush works with a circle. If you want to move the origin of the gradient, and want to keep the origin in the circle, keep checking to make sure that your coordinates are in the circle.
Using the XAML above the origin of the gradient is place three quarters down the border and one quarter in from the left edge.
1d. The RadiusX and RadiusY properties.
Unless you set the RadiusX and/or the RadiusY properties of the brush you are always working with a perfectly round circle. The easiest way that I can think of describing what the radiusx and radiusy properties do is to say that they control the height and width of the outer circle, or end point, of the gradient.
Remembering that 0.5 is the value that gives you an even circle, you increase or decrease the amount from there.
Setting radiusx to a value of .25 makes the brush more of a vertical ellipse than a circle.
In the same way the radiusx controls the width of the brush radiusy controls the height.
Using the same value as with the radiusx example, setting the value of radiusy to .25 gives an ellipse that is wider than high.
1e. Adding colours to the Brush.
Colours, or GradientStops, are added to the radialgradientbrush in the exact same way as the lineargradientbrush. You just need to add a gradientstop to the collection of gradientstops of the brush and set a value for the color and offset properties.
By adding the third colour our brush now looks like the following.
A friend asked me recently if it was possible to access resources that were created and stored in a separate assembly. Although I was sure it could be done, I’d never tried it, so I was interested in experimenting with this idea. It turns out that the Pack URL holds the key. Here’s an example.
Access a single ResourceDictionary
In a ResourceDictionary file named Dictionary1.xaml inside a standard WPF Application project named ‘Resources’, I have the following markup:
1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
3 <LinearGradientBrush x:Key="MyBrush">
4 <GradientStop Color="Black" Offset="0"/>
5 <GradientStop Color="Yellow" Offset="1"/>
6 </LinearGradientBrush>
7
8 <Style x:Key="RedButton" TargetType="{x:Type Button}">
9 <Setter Property="Background" Value="Red"/>
10 <Setter Property="Foreground" Value="Yellow"/>
11 <Setter Property="Margin" Value="12,3"/>
12 <Setter Property="Padding" Value="3"/>
13 <Setter Property="MinWidth" Value="75"/>
14 <Setter Property="MinHeight" Value="34"/>
15 </Style>
16 </ResourceDictionary>
Very basic resources, I know, but sufficient to demo the process. The next step is to create the ‘client’ project, the one that will use this resource. You can either add a new project to the current solution or start a completely separate solution. In my first example, I added a WPF Application project to the solution and named it ‘ResourceUser’.
In either case, you need to add a reference to the ‘Resource’ project in the Reference section of the ResourceUser project. If you add a second project to the current solution, the project name will be available to you in the Projects tab of the Add reference dialog (as shown in the screenshot below). If you use a separate solution, you’ll have to use the Browse tab and navigate your way to the required assembly.
This enables you to point to the source file, i.e. the ResourceDictionary named Dictionary1.xaml in the Resource project. The way you point to that resource is to create a ResourceDictionary in the Application.xaml file of the client project, the project that I named ResourceUser. You set its Source property to the Dictionary1.xaml file. As I said at the start, you use the pack URL syntax to do this. Here’s the syntax that does the job:
1 <Application x:Class="Application"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 StartupUri="Window1.xaml">
5 <Application.Resources>
6
7 <ResourceDictionary Source="pack://application:,,,/Resources;component/Dictionary1.xaml"/>
8
9 </Application.Resources>
10 </Application>
To avoid confusion, I probably should have named the first project something like ‘ResourceDictionarySource’, but anyway I’m sure you’ll understand that the word ‘Resources’ in that Source property refers to the name of the project. You’ll also see that the Dictionary1.xaml file name is included as the final item. The general syntax for the pack URL approach is:
pack://application:,,,/<Name of project you are referencing>;component/<Name of specific file you want to access>
Once you’ve rebuilt the project, you can use the referenced resources just as you would if they existed in the client project. To use the gradient brush and the button styles from my example above, you can do something like this in the Window of the ResourceUser project:
12 <Button Style="{StaticResource RedButton}" Content="Demo" Margin="52,21,127,0" Grid.Row="1" Height="22" VerticalAlignment="Top" />
13 <Rectangle Margin="52,28,127,17" Name="Rectangle1" Stroke="Black"
14 Fill="{StaticResource MyBrush}"/>
Access multiple ResourceDictionaries
If the project that has the resources contains more than one ResourceDictionary, then you can use a MergedDictionaries block in the Application.xaml file of the client project. The following example assumes that the Resources project now contains two separate ResourceDictionary files named Dictionary1.xaml and Dictionary2.xaml:
5 <Application.Resources>
6
7 <ResourceDictionary>
8 <ResourceDictionary.MergedDictionaries>
9 <ResourceDictionary Source="pack://application:,,,/Resources;component/Dictionary1.xaml"/>
10 <ResourceDictionary Source="pack://application:,,,/Resources;component/Dictionary2.xaml"/>
11 </ResourceDictionary.MergedDictionaries>
12 </ResourceDictionary>
13
14 </Application.Resources>
What if you have ResourceDictionaries in the client project too?
This doesn’t present any kind of problem. You simply add the ResourceDictionary to the MergedDictionaries collection in the usual way. For example, if you have a ResourceDictionary named ResourceDictionary3.xaml in the ResourceUser project, you can use this syntax in Application.xaml:
7 <ResourceDictionary>
8 <ResourceDictionary.MergedDictionaries>
9 <ResourceDictionary Source="pack://application:,,,/Resources;component/Dictionary1.xaml"/>
10 <ResourceDictionary Source="pack://application:,,,/Resources;component/Dictionary2.xaml"/>
11 <ResourceDictionary Source="Dictionary3.xaml" />
12 </ResourceDictionary.MergedDictionaries>
13 </ResourceDictionary>
What about resources that use their own resources?
So what happens if for example you have a ControlTemplate that uses images that are stored as resources in the Resource project? Well, this isn’t a problem at all because the whole Resource project is referenced, so if the template calls for a resource file in that project when it is used in the client project, that file is available.
If that explanation isn’t as clear as you’d like, here’s an example. In the Dictionary2.xaml ResourceDictionary, you have a Control Template for a CheckBox that uses three images. Here’s the first part of the markup for the CheckBox Control Template:
6 <ControlTemplate x:Key="ThumbCheckBox" TargetType="{x:Type CheckBox}">
7 <Border Name="OuterBorder"
8 BorderBrush="Black" BorderThickness="1">
9 <Canvas Name="MainCanvas">
10 <Border Name="ImagesBorder" BorderBrush="DarkGray" BorderThickness="1"
11 Width="24" Height="32" Margin="1,1,0,0" >
12 <Canvas Name="ImagesCanvas">
13 <Image Name="ThumbDown" Source="ThumbDownSmall.jpg" Width="18" Height="26"
14 Canvas.Left="2" Canvas.Top="2"/>
15 <Image Name="ThumbUp" Source="ThumbUpSmall.jpg" Width="18" Height="26"
16 Margin="1" Canvas.Left="2" Canvas.Top="2"
17 Visibility="Hidden"/>
18 <Image Name="Indeterminate" Source="QuestionMark.jpg" Width="18" Height="26"
19 Margin="1" Canvas.Left="2" Canvas.Top="2"
20 Visibility="Hidden"/>
21 </Canvas>
You can see that there are three jpgs involved in the creation of that template.
They are all stored in the project with a Build Action of Resource. One of the images is named ThumbDownSmall.jpg and you can see it shown in the Solution Explorer, together with its properties in the Properties pane:
If you assign this ControlTemplate to a CheckBox instance in the Window of the client project, the required images will be pulled from the Resources project as and when they are needed. The following XAML in the client project uses the template:
<CheckBox Name="chkApproval" Margin="52,14,111,36" Grid.Row="2"
Template="{StaticResource ThumbCheckBox}"
Content="Not Approved"
IsChecked="{x:Null}"
IsThreeState="True">
</CheckBox>
And the result is the CheckBox you can see at the bottom of the Window:
You can download the sample solution I used for this blog post. It's available as a blog attachment or can be downloaded from here.
I saw that the LearnDevNow site is offering a big discount on their standard price, so thought it worth checking out their offerings.
You can either subscribe to one or more of six technology areas:
or for much better value, subscribe to the whole range of more than 2,500 videos. It’s an annual subscription basis – currently $49.99 for one technology or $99 for the whole set. Videos are streamed on line. Although I would have preferred to be able to download videos and watch in my own time, e.g. when travelling and out of internet range, I understand that the reason behind their approach is to try and stop piracy.
At the time of writing, the VB and C# videos have topics in detail up to the 2008 editions of Visual Studio. There are also Exploring VS 2010 courses for both VB and C#. Other 2010 courses are already being produced and they will automatically be added to the available titles as part of the subscription at no additional cost when they are written.
The courses that I’ve looked at so far all take the same approach. First, there’s a general overview intro, followed by a more detailed introduction of the topic that mostly uses PowerPoint slides. Then the explanations are followed up with hands-on code demonstrations interspersed with more audio and slides.
The explanations are clear and of course you have the advantage of being to view difficult sections over and over if you need to. The content of each module is listed in the Module pane at the left hand side of the main window, so you can jump forward or back to sub-areas of content at will. You can see these in the screenshot below.
I was a bit confused by the pause feature at first. If you click on the progress bar in the screen shot above, the video will pause and then restart automatically after a preset delay. By the way, if the thumb button of the progress bar is hidden (as it is above by the Power Point slide) you can still just click anywhere on the bar to pause play.
If you want more control over the pause and restart functions, then I found that it was best to use the full screen mode. You can see the button for invoking this in the screenshot down at the bottom right. Once things are running in full screen mode then any key click on the window will pause play. It will then stay paused until you click again or until you return to the default viewer display. The Esc key will close down full screen mode for you.
The Stretch button causes the video display to increase to fill the black client area you can see in the screenshot.
I don’t have a very fast broadband connection at home, but I found that every video I viewed streamed smoothly and with none of the buffering delays that can drive you mad while you wait for it to catch up.
Overall, the presentations were clear, relevant and comprehensive. The presenters know their stuff and present it in a logical order and understandable format. It’s clear that a lot of time and effort has gone into the production. If you’re one of the many people who find that a moving picture is better than a thousand words when it comes to learning, then I think you’ll find this collection of courses to be good value.
Visual Basic and C# are by far the two most popular .NET languages. With the 2010 releases of both, Microsoft has announced the intention to keep them as even as possible, putting new features into both at the same time. Both languages compile to the same intermediate language, and there are translators that can pretty much take code in one and turn it line by line into the other. The decision to use one over the other is really a personal preference, not based on the performance or capability of the language.
I now develop in both languages, and here are a few of the differences, with my impressions of which has the better syntax. I encourage people to expand on my list, but hopefully refrain from bashing their second choice.
Function, Sub, Method
VB
Private Sub DoSomeWork()
Private Function Add5(ByVal n As Integer) As Integer
C#
private void DoSomeWork()
private int Add5(int n)
Visual Basic has Functions and Subroutines. C# has no equivalent keyword for either, although the concept is called a Method. The VB Function Add5 has a return type "As Integer"; the C# method Add5 has "int" in its signature before the method name. VB Subroutines become C# methods with a return type of "void" (no return type).
My personal preference in this case is for the C# syntax. The method name and its return type are conveniently right next to each other. In a VB Function with a lot of parameters, looking for the return type can be like waiting for the verb in a German sentence.
Variable declaration
VB
Dim x As Integer = 5
C#
int x = 5;
Again, I prefer the C# syntax because the variable and its value are together. The VB syntax looks like you're assigning 5 to "Integer". Also, C# is slightly less verbose.
Comparing values
VB
If (a = 7) Then
C#
if (a == 7)
The two equal signs in the C# example are not a typo. In C#'s predecessor language, C, the simple statement above was a giant problem waiting to happen. If you typed a single = symbol, the statement would:
The reason for this behavior is that if (a = 7) was evaluated as "assign a = 7" and "was the assignment successful?"
The C# IDE prevents you from typing the single = sign. Visually, it's just something to get used to. I think VB wins this one.
ByRef parameters
VB
Dim myInt As Integer = 5
Dim myBool As Boolean = CubeInt(myInt)
Private Function CubeInt(ByRef i) As Boolean
C#
int myInt = 5;
bool myBool = CubeInt(out myInt);
private bool CubeInt(out i)
Select Case processing
VB
Select Case someVar
Case 5
DoSomething()
Case 1, 2, 3
DoSomethingElse()
Case Else
DoThirdThing()
End Select
C#
switch(somevar)
{
case 5:
DoSomething();
break;
case 1: case 2: case 3:
DoSomethingElse();
break;
default:
DoThirdThing();
break;
}
In this case, I think VB has the edge. "break;" is a carryover from C and C++, where it is optional. Without it, control goes to the next line following the next case choice, probably not what you mean. Since the Visual Studio C# editor doesn't even allow you to omit break, the C# team is simultaneously recognizing that the fall-through behavior is a bad idea and making you code around it anyway (instead of just working as VB does). Also, I like that VB allows you to list values with commas instead of repeating the case as C# does.
Miscellaneous observations
C# doesn't care if you type a statement with a lot of carriage returns, running onto multiple lines. This is also true in VB 2010, but before that you needed the "_" (underscore) as a continuation character.
C# statements end in semicolons. Over an average career, I'm sure that a C# developer types tens of thousands of semicolons. I'm willing to bet that this time could be saved by a small tweak to the compiler to infer the line ending. (Javascript is able to do this, and it runs interpreted.) Even with the semicolons, C# is less typing than VB.
C# variables are case-sensitive, which is one of the few ways in which the two languages cannot entirely translate back and forth. "Bob" and "bob" could both be variables in the same C# program, and I think this is a really bad idea.
VB programs are slightly more English-like, and less intimidating to discuss with a non-programmer. This comment can also be applied to COBOL, which is definitely out of favor these days.
Conclusion
Both languages are very powerful, and virtually interchangeable. The most compelling argument I've heard one way or the other is that there seems to be a greater market demand for C#.
I've listed only a few of the differences, and I encourage others to add to my list. I may post more on this topic soon.
This post deals with the last two brushes that can be used in a Silverlight 3 project. These are the ImageBrush and VideoBrush.
Part 1 I took a look at the SolidColorBrush and the LinearGradientBrush. Part 2 examined the RadialGradientBursh.
ImageBrush
The imagebrush takes an image and paints the element with that image.
You are not limited to using the two brushes described in this post only on fonts this is just how I decided to use them as an example.
Any element, or element property, that can have a brush applied to it can make use of the imagebrush.
For this example I am using a TextBlock with a large letter T.
You can either have the image compiled as a resource into your project or you can have it as a relative file or even any file accessible to your silverlight application.
For this example I am going to use an image file that is in a relative position to me application. The first thing required is to add the image to the ClientBin directory so it is with the xap file of the application.
An imagebrush is defined between the opening and closing tags of the foreground property of the textblock.
While there are several properties for the brush that you can set the only required property is the ImageSource. The imagesource takes the Uri of the image you want to use. This Uri can be a relative or absolute. Since the image in this example is in the same directory, and run off of the same web site, a relative Uri is used.
When the project is run you can see that the image has been applied to the letter.
VideoBrush
The videobrush allows you to play a video on the element it paints.
As with the image used in the imagebrush the video file you use can be compiled into the application or be used as an external resource. Unless your video is very small you would most likely want to use videos which are external resources only.
So as a beginning a Windows Media File (.wmv) is added to the project in the same directory as the xap file for the silverlight application.
You would think that you would just define a video as the source of a videobrush and you would be off. Though this approach works with an imagebrush, it is not the way a videobrush works.
The videobrush actually makes use of another element as its source. The element which is used is the MediaElement.
Basically the mediaelement is a video player which is then, when defined in the videobrush is painted onto the element the brush is for.
When you define the Mediaelement you need to add a minimum of two properties. These properties are the Name, Source.
You give a name to the mediaelement because when you set the SourceName of the brush you use the name for the mediaelement. The source of the mediaelement can be a relative or absolute Uri. Since the video is in the same directory as the application a relative Uri is used.
Depending on how you are making use of the video brush would determine on the setting of the other two properties that I have defined in the XAML above. Using the brush for text as I am in this example, I have set the opacity to 0 so the mediaelement is not visible. If I did not do this, the video would show behind the text. The other property I set is the IsMuted since you probably would not have sound if you use this method for text.
To apply the mediaelement to the brush you just need to put the name of the mediaelement in the SourceName property of the videobrush.
Unfortunately due to this being non-silverlight blog you can’t see the video playing here. If you were to make a project following the steps above you would see the video playing nicely in the bounds of the letter.
*Note:
Not all video formats are supported by the mediaelement. Check out MSDN for a list of supported formats.
Here is a simple tutorial on how to read, compile, and run code that is written in a text file. In this example, we will be reading properly formatted VB.NET code from a text file which will change the text of a TextBox in a Windows Forms application to "Hello vbCity!!" when a button is pressed.
frmMain
Here is the code contained in the text file (Code.txt). This file located in the project's bin directory (ensure you set it to "copy if newer") in the file properties section of Visual Studio. This is the code we will be compiling and running from our WinForms application.
txtOutput.Text = "Hello vbCity!!"
Now, to the meat of the sample. There are a few simple steps we must complete to read, compile, and run the code. In order:
All these steps are in order in the following code fragment. This code is executed when the "Press Me" button is clicked.
Imports System.IO
Imports System.Reflection
Imports System.CodeDom
Imports System.CodeDom.Compiler
Imports Microsoft.VisualBasic
Public Class frmMain
' Button to start compiling code.
Private Sub btnPressMe_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPressMe.Click
' Read code from file
Dim input = My.Computer.FileSystem.ReadAllText("Code.txt")
' Create "code" literal to pass to the compiler.
'
' Notice the <% = input % > where the code read from the text file (Code.txt)
' is inserted into the code fragment.
Dim code = <code>
Imports System
Imports System.Windows.Forms
Public Class TempClass
Public Sub UpdateText(ByVal txtOutput As TextBox)
<%= input %>
End Sub
End Class
</code>
' Create the VB.NET compiler.
Dim vbProv = New VBCodeProvider()
' Create parameters to pass to the compiler.
Dim vbParams = New CompilerParameters()
' Add referenced assemblies.
vbParams.ReferencedAssemblies.Add("mscorlib.dll")
vbParams.ReferencedAssemblies.Add("System.dll")
vbParams.ReferencedAssemblies.Add("System.Windows.Forms.dll")
vbParams.GenerateExecutable = False
' Ensure we generate an assembly in memory and not as a physical file.
vbParams.GenerateInMemory = True
' Compile the code and get the compiler results (contains errors, etc.)
Dim compResults = vbProv.CompileAssemblyFromSource(vbParams, code.Value)
' Check for compile errors
If compResults.Errors.Count > 0 Then
' Show each error.
For Each er In compResults.Errors
MessageBox.Show(er.ToString())
Next
Else
' Create instance of the temporary compiled class.
Dim obj As Object = compResults.CompiledAssembly.CreateInstance("TempClass")
' An array of object that represent the arguments to be passed to our method (UpdateText).
Dim args() As Object = {Me.txtOutput}
' Execute the method by passing the method name and arguments.
Dim t As Type = obj.GetType().InvokeMember("UpdateText", BindingFlags.InvokeMethod, Nothing, obj, args)
End If
End Sub
End Class
When ran, the output show display:
You could also change the text to something a little more elaborate, such as:
Dim sum As Integer = 0
For i As Integer = 1 To 100 Step 10
sum += i
Next
txtOutput.Text = Convert.ToString(sum)
When executed, it will output:
And for a C# version (minor changes):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.CodeDom;
namespace WinFormCodeCompile
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Load code from file
StreamReader sReader = new StreamReader(@"Code.txt");
string input = sReader.ReadToEnd();
sReader.Close();
// Code literal
string code =
@"using System;
using System.Windows.Forms;
namespace WinFormCodeCompile
{
public class Transform
{
public void UpdateText(TextBox textBox1)
{" + input + @"
}
}
}";
// Compile code
CSharpCodeProvider cProv = new CSharpCodeProvider();
CompilerParameters cParams = new CompilerParameters();
cParams.ReferencedAssemblies.Add("mscorlib.dll");
cParams.ReferencedAssemblies.Add("System.dll");
cParams.ReferencedAssemblies.Add("System.Windows.Forms.dll");
cParams.GenerateExecutable = false;
cParams.GenerateInMemory = true;
CompilerResults cResults = cProv.CompileAssemblyFromSource(cParams, code);
// Check for errors
if (cResults.Errors.Count != 0)
{
foreach (var er in cResults.Errors)
{
MessageBox.Show(er.ToString());
}
}
else
{
// Attempt to execute method.
object obj = cResults.CompiledAssembly.CreateInstance("WinFormCodeCompile.Transform");
Type t = obj.GetType();
object[] arg = { this.textBox1 }; // Pass our textbox to the method
t.InvokeMember("UpdateText", BindingFlags.InvokeMethod, null, obj, arg);
}
}
}
}
Transforms are used to shift or alter the way an element is drawn. These transforms include SkewTransform, ScaleTransform and TranslateTransform. These transforms include SkewTransform, ScaleTransform and TranslateTransform.
The first transform I am going to look at is RotateTransform.
RotateTransform
RotateTransform is used for the process of rotating an element to a certain angle around a central point.
For this example I am starting with a button placed in the centre of a 400x400 grid.
When you use RotateTransform on an element it is rotated on a set of x and y coordinates. The x and y coordinates start at the top left corner of the element, which would be position 0,0 and run down and to the right. The first number in the coordinates represents the value along the x-axis and the second number follows the y-axis.
You can’t just add the RotateTransform to the element directly, you must add it to the RenderTransform property of the element. To do this you must use the element-property syntax in the XAML to set the transform since it is a complex property.
So the first step is to add tags to the RenderTransform property of the element. This will hold the transform information which will be then used to render, or draw, the element.
1. Setting the Angle of rotation.
Once you have the property declared you can add the basic definition of the rotatetransform.
There is only one property of the rotatetransform that you need to define. This property is the Angle. The angle takes any value from 0 to 360 both positive and negative. You actually could use any number, but using a number more than +/- 360 degrees is just making the markup more complicated than it needs to be.
By setting the angle to 45 and running the project, the button is now displayed on an angle.
Without setting anything other than the angle the element will rotate from its 0,0 coordinates, or the top left corner.
There are three different ways that you can set the rotation point. You can set the value along the x-axis only, they y-axis only, or both the x and y axis. If you do not specify point along the x or y axis the value will be set to the default of 0.
2. Setting the Rotation point.
2a. Rotating on the x-axis.
If you just want to rotate an element on its x-axis, you give a value to the CenterX property when you define the transform. The easiest way I can think of describing what value to use for the x-axis is to think of it as the same as the width of your element.
In this example the button is 200 points wide, so the value of CenterX would be set somewhere from 0 to 200. You can still use any positive or negative value for the property you are not limited at all to the width. (You do need to keep in mind, however, that if you use a number less than 0 or greater than the width of the element that it may actually move to a different location, not just rotate.)
Setting the CenterX property to 100, which is half the width of the button, when the project is run the button now rotates at the 100,0 position or half way along the top of the button.
2b. Rotating on the y-axis.
Where the x-axis represents the width of the element, the y-axis is represented by the height of the element. The value along the y-axis is used to set the CenterY property when the transform is defined. You don’t need to give the CenterX property a value at the same time as defining one for CenterY. If no value for CenterX is defined then the default value of 0 is used.
Here, CenterY is set to 50, which is half the height of the button. When the project is run the button the centre point of rotation will be half way down the left side of the button.
Just like the values you can use for the CenterX property, you are not limited to a minimum of 0 or maximum equal to the height of the element you are rotating. You can use negative numbers or a value higher than the height of the element. Again you must remember if you do go outside the 0 to element height bounds that your element may move to somewhere you don’t want it to as the rotation centre point will no longer be on the element but outside its bounds.
2c. Rotating on the x and y axis.
To rotate your element at a point which is not along either the top or left of your element requires you to set both the CenterX and CenterY properties. By setting both properties in your definition you can have the rotation centre point anywhere inside the element. Again you are not limited to the boundaries of the element but it will move in the layout container if you use a value that is not within the element.
The XAML above sets the rotation centre point to be in the middle of the button.
3. The resizable element.
Using the above techniques is good, perfect even, for an element that does not change size.
What happens if your user interface is resizable?
With Silverlight, and WPF, being resolution independent this is a very real possibility you may find that setting a CenterX and CenterY value will not work because your target element may end up being smaller than the original height and width.
Does this mean that you can’t rotate the element?
No, it does not.
Instead of defining an x and y value when you define the transform you need to set the RenderTransformOrigin property of the element itself.
The property also takes a set of x and y coordinates, but they differ slightly from the transforms x and y. The RenderTransformOrigin take a value from 0,0 (top left corner of the element) to 1,1 (bottom right corner). By setting this property it means that even if your element is smaller, or larger, that it will still have the same rotation centre point.
A set of coordinates of 0.5,0.5 will give the same result as setting the CenterX and CenterY values as I did above and the button is rotated around a point in its exact centre.
While you can use numbers smaller than 0 or larger than 1 as one of your coordinates, the same warning as above applies in which your element will move to an unexpected location on your layout element.
In the first part this look into transforms the RotateTransform was examined.
This post is going to take a look at the SkewTransform.
SkewTransform.
The skewtransform basically takes any rectangular element and turns it into a parallagram. The transform accomplishes this by skewing the value of either the x or y axis by a degree assigned when the transform is defined.
Even though I say a rectangular element, this does not mean that non rectangular elements can’t have a skewtransform applied to them. They can. Non-rectangular elements get the transform applied as if the element itself is in a rectangular container and the transform is then used on the invisible container.
For this example I am have a button in a grid with a semi-transparent rectangle overlaying the button. The reason I am using the rectangle is to show how the button is changing as the transform is applied.
Like all transforms you can’t just define the transform to the element directly, you must add it to the RenderTransform property of the element. To do this you must use the element-property syntax in the XAML to set the transform since it is a complex property. Then you can add the base definition for the transform.
1. Setting the Angle.
Setting the angle(s) of a skewtransform is similar to setting the angle of a rotatetransform, but how the skewtransform applies the angle is much different and can be much more complicated.
The skewtransform has two angle properties that affect how the element is drawn. These properties are the AngleX and AngleY.
The easiest way that I can think to describe how the angles work is that they alter, or skew the opposite axis. What this means is that if you give a value to AngleX then it is the y-axis, left side, of the element which is skewed. Setting the AngleY changes the x-axis, top, which is skewed.
Another way to look at it is setting the AngleX will move the bottom of the element to the left or right depending on the angle applied and the AngleY will move the right side of the element up or down depending on the angle.
Values for the AngleX and AngleY range from 0 to 90 both positive and negative though if you use a value of 90 then your element would not be visible. You can use values higher than 90, but if you do it would find that instead of skewing to the right or down your element would skew from the left or up.
1a. Setting a single Angle.
Depending on the requirements of your design, the minimum that you need to add to the definition of a skewtransform is a value for either the AngleX or AngleY property.
In the XAML above I have set the AngleX to 45 degrees which moves the y-axis side so it is on a 45 degree angle from the top left corner of the button. By default unless defined Silverlight will use 0 as the centre point of the transform.
Giving a value to AngleY skews the button along the x-axis, top, at a 45 degree angle.
You can see that the right side of the button has moved down at the defined angle. Again because no centre point was defined the transform was applied from the top left corner of the element.
1b. Setting more than one Angle.
You do have the ability to give values for both the AngleX and AngleY properties when you define the transform. You are not limited in any way to just having to use one.
By setting values to both the angle properties you transform both the x and y axis of the element. The element is skewed from the top left, or 0,0, point because no centre point was defined.
2. Setting Centre Points.
If you don’t give explicit values for the centre points when you define the transform, then the default value of 0 is applied to the CenterX and CenterY properties.
The CenterX property refers to a point along the top of the element and the CenterY refers to a point down the left side of the element.
The centre points determine where the transform is applied to the element keeping in mind that the value of AngleX is applied to the CenterY point and the value of AngleY is applied to the CenterX point.
When you define the transform if you only set a value for AngleX, that value will have no affect on how the CenterX axis of the element and vice versa for the AngleY and CenterY.
By only giving CenterX a value above the center point of the transform is 50,0 but as you can see in the following screen shot that only the y-axis is skewed so this has the same effect of not having set a CenterX point at all because the x angle does not affect the x-axis.
If the CenterX in the previous XAML was changed to CenterY and given a value of half the height of the button we get a much different skewing of the button.
The center point of the skew is now 0,25 and you can see that the button is still skewed at a 45 degree angle, but the transform starts half way down the left side of the button.
You can set both centre points if you want, but if don’t give values for both angles then it may not have the affect you are expecting.
The following has a centre point of 25,25 but because only an AngleX was defined the button only skews half way down the left side. There is no skewing of the top side.
The same thing happens if only the AngleY is defined.
The top of the button gets the transform applied, but the left side stays the same.
3. The complete transform.
(Ok, perhaps not the best title, but it will do.)
Naturally you can set values for all four properties and skew both sides of the element at once.
The XAML above skews the button at an angle of 25 degrees starting at 50 point along the top and also down right side 25 points the 25 degree skew starts.
4. The shrinking, or growing, element.
I brought this up in my look at the RotateTransform, and it also applies here too.
Using absolute values for the CenterX and CenterY properties is fine if the size of the element never changes, but because the size of the element could change in Silverlight using such static values may best.
Instead of setting the CenterX and CenterY in the definition of the transform, you can use the RenderTransformOrigin property of the element itself.
You set the rendertransformorigin property with a set of x and y coordinates with a value of 0.0 to 1.0. Also by using the rendertransformorigin property I don’t have to declare a CenterX or CenterY when I define the transform.
Setting the coordinates to 0.5,0.5 as I did above will skew the element at 25 degrees along both the top and left side no matter what size the element becomes.
I often write blogs about problems that I’ve had and which, eventually, I’ve managed to solve. This is one of them.
If you’ve landed on this blog because you’ve seen this error message, you’re probably trying to create a report with the ReportViewer control. (There are other scenarios where this message might appear, but this is the one I’m working on.)
In my case, the message came up when I tried to run a fairly simple report in a Windows Form using the ReportViewer control in Visual Studio 2010.
So of course I did the usual internet search and came up with lots of forum questions and answers and other results. None of them applied to my situation though. Many of the questions had been posted before VS 2010 shipped, so users were using VS 2008. That version of Visual Studio uses a different variety of ReportViewer.
As is so often the case, the answer was very simple, with the benefit of hindsight. The cause, by the way, was that in the Report Designer I had changed the report’s data source from one data set to another. Now, the report was quite happy to accept this change and I was able to change the fields that I used in the body of the report.
But what didn’t change was the TableAdapter that the ReportViewer was relying on over in the Windows Form. So when I tried to run the project, there was a mismatch between what the Report was offering to display and what the ReportViewer thought it needed. You might have thought that this change of TableAdapter would be done automatically. I certainly did and that’s the danger with technology that does so much under the covers for you. You get lulled into a belief that everything will somehow be magically taken care of for you.
Anyway, the fix is very simple. Click on the smart tag of the ReportViewer. You will see that one of the choices is 'Choose Data Sources’.
You will then see a Choose Data Sources dialog window. Click at the right hand side of the Data Source Instance column a small arrow will appear. Click on this arrow and a new row will be created. This may have the rather unhelpful choice range of ‘(none)’ as shown below, depending on what bindings you have in place for the form.
Click at the right hand side of the Data Source Instance column again, this time inside the second row. The small arrow will appear again and you will see the beginning of a tree of elements. Navigate through the options until you find the data source you want to use.
Once you’ve correctly made the selection that matches the report that’s currently assigned to the ReportViewer, click OK. With the binding in place, run the project again and it should now run correctly and your report will be displayed.
I got to thinking that it would be a really good idea if I posted up some working examples of Brushes so anyone could change some of the properties of a Brush and see how they look and work to go along with the posts that I have done.
The page can be found here.
You can change properties of the LinearGradientBrush, RadialGradientBrush and ImageBrush as well as see a VideoBrush in action.
Other posts in this series of a look at Silverlight transforms are RotateTransform and the SkewTransform.
In this post I am going to take a look at the ScaleTransform.
ScaleTransform is used to stretch or shrink an element either along its x-axis or y-axis.
The transform is applied from a central point which is defaulted to 0 on the x-axis and 0 on the y-axis. This default point is the top left of the element.
1. Setting up the project.
For this project I am starting with a button centred in the middle of a 400x400 grid. I have put a semi-transparent rectangle on top of the button so when the values are changed you will be able to see the original position and size of the button.
Transforms can’t just defined directly to the element, you must add it to the RenderTransform property of the element. To do this you must use the element-property syntax in the XAML to set the transform since it is a complex property. Then you can add the base definition for the transform.
2. Settng ScaleX and ScaleY.
The value of the ScaleX property determines how much the element the transform is applied to will grow or shrink along the x-axis. Another way to look at it is the ScaleX value will change the width of the element.
A value of 1 represents the current size of the element.
To increase the size of the element you would obviously use a larger number. You are not limited to whole numbers for the value of ScaleX you can use a decimal as well.
The XAML above stretches the button to one and a half its original width.
ScaleY works exactly the same as ScaleX. You just need to put in a value larger the 1 to increase the height of the element.
A value of 1.5 will make the button grow half again along the y-axis.
You can set new values for both the ScaleX and ScaleY properties at the same time, you are not limited to only changing one or the other.
Applying new values to both properties makes the button stretch to one and a half times it size.
You must keep in mind that unless you specify differently your element grows to the right and down from its default centre point which is the top left corner. Changing the centre point is looked at a little later in this post.
2b. Setting ScaleX and ScaleY to make the element smaller.
You can also make your element shrink by using a number smaller than 1 but there is one small, sorry no pun intended there, detail when you get to using negative numbers. I will get to that in a second.
To make your element smaller you just need to set the value of ScaleX or ScaleY to a decimal number larger than 0. If you use 0 as a value your element will actually not be visible so you would most likely not ever use it.
Setting the ScaleX to .5 shrinks the button to half its defined size.
2c. Using negative numbers for ScaleX and ScaleY.
You can use a negative number for setting ScaleX and ScaleY, but the results may not be what you expect.
A value of -1 for ScaleX
will actually flip the element over and you will see the back of the element similar to opening a door.
If you use a lower negative number, such as -1.5, the element would still stretch but it stretch to the left after the element has flipped.
Using negative numbers for ScaleY works the same.
A value of -1 flips the element up so you see it upside down.
3. Centre Points.
The centre point of a ScaleTransform is the point from which the transform is applied to the element. If either coordinate of the centre point is not 0 the element is scaled both left and right, or up and down from the defined point.
By setting the CenterX value to 50 as I have below, the button will now grow both to the left and right by 1.5 times and down by 1.5 times the height of the control.
You can see from the screen shot below that the button has scaled 75 points to either side of the centre point.
Setting a CenterY property gives a similar result along the y-axis.
The button is scaled both up and down from the CenterY point.
You can set either one or both CenterX and CenterY to cause your element scale from any position that you want.
The XAML above makes the button 1 ½ times larger in the same location as the original button.
4. Using RenderTransformOrigin.
Since your element may not always stay the same size you may not want to use absolute values for the centre point of your Transform.
If this is the case then you will want to set the RenderTransformOrigin property of the element itself.
The value of rendertransformorigain are an x and y set of coordinates where the values commonly are from 0 to 1 where 0,0 is the top left corner of the element and 1,1 is the bottom right of the element.
Setting the x and y both to 0.5 the button scales from the centre of the button no matter what size it is.
This is the fourth post in the series of looking at Transforms in Silverlight. The first post looked at RotateTransform, the second SkewTransform and the third examined ScaleTransform.
This post will look at the easiest of the transforms the TranslateTransform.
The TranslateTransform takes the element you apply it to and draws it in another position determined by a set of x and y coordinates.
The transform is applied from a central point which is defaulted to 0 on the x-axis and 0 on the y-axis. This default point is the top left of the element.
1. Setting up the project.
For this example I am using a button that is centred in a 400x400 grid. A red semi-transparent rectangle has been placed over the button to show the original position once the transform has been applied to the button.
Transforms can’t just defined directly to the element, you must add it to the RenderTransform property of the element. To do this you must use the element-property syntax in the XAML to set the transform since it is a complex property. Then you can add the base definition for the transform.
2. The X and Y properties.
2a. Setting X.
When you give the X property of the translatetransform a value your element will move along the x-axis, to the left or right, from its original position.
You can use both positive and negative numbers as a value for the X property.
Above I have set the value to X to 50 and when the project is run the button is drawn 50 points to the right of its original position.
2b. Setting Y.
As you would expect giving a value to the Y property will move the element along the y-axis which will draw the element up or down from its starting position.
A positive value, like the example above, draws the button lower and a negative value would have moved the button up.
2c. Setting X and Y.
If you want to re-draw your element in both directions all that is needed to give values to both the X and Y properties.
Positive values draws the element down and to the right.
Setting the values to negative numbers does the opposite.
The element is drawn up and to the left.
3. Resizable element and RenderTransformOrigin.
With the nature of Silverlight being resolution independent it is possible that your element may not always be the same size and therefore you will not want to set only the X and Y properties.
In the case that you want to redraw your element, and it is possible that the element may change size, you need to set the RenderTransformOrigin property of the element.
The x and y coordinates values of the rendertransformorigin range from 0 to 1 and run from the top left corner of the element, position 0,0, and move to the lower right corner, position 1,1.
Using rendertrnasformorigin guarantees that your element will be drawn where you want it regardless of its size.
This is the last post in the look at transforms in Silverlight. The first post looked at RotateTransform, the second SkewTransform, the third ScaleTransform and the fourth examined TranslateTransform.
Each of the posts showed how to apply one transform to a silverlight element and you may be wondering if you can apply more than one transform to an element at a time.
The answer to that is a definite yes, otherwise there would be no point to this post.
1. Setting up the Project.
For this example I am using a button that is centred in a 400x400 grid. A semi-transparent red rectangle has been placed over the button to show the original position once the transforms have been applied to the button.
2. Adding Transforms.
As you learned in the other posts, if you have read them, transforms are added to the RenderTransform property of the element.
There is a catch to the rendertransform property however and that is it can only hold one transform. If you want to use more than one transform for an element you must put the transforms into a TransformGroup within RenderTransform.
Once the opening and closing tags for the transformgroup are in place, you can start adding the transforms you want to apply and give values to the properties you want to change.
(*Note:
When I first drafted this post I was going to show adding the transforms one at a time, but since I had already covered the transforms themselves in other posts I decided to leave those steps out. If you want to look at the individual transforms then use the links at the start of this post and visit the pages for the transforms.)
In the XAML above I have set a property, or two, from each of the transforms.
The button is rotated down 45 degrees, scaled up to 1.5 times its original size, skewed 45 degrees along the x-axis and moved 40 points to the left and 80 points up from its original position.
If you use multiple transforms the transforms are applied in the order that they are defined.
Also remember that three of the transforms looked at have properties that are the same. For example CenterX and CenterY are both properties of the RotateTransform, ScaleTransform and SkewTransform. You can set the CenterX from any of the three.
Even though by default CenterX and CenterY is 0 when you define a transform, the value that has been set in the rotatetransform is carried over to the other two transforms that have CenterX and CenterY proeperties. Which kind of goes against what I mentioned previously about the transforms being applied as they are defined because even though I have not given values in the scale and skew transforms the values are not re-set to 0 when the next transform is applied.
In the case of CenterX and CenterY, if you do set the values for them in more than one transform, the CenterX and CenterY values that used for the final drawing of the element will be the last value defined and will be set from the original position of the element.
(*Note:
There is only little gotcha with my last statement.
There is only little gotcha with my last statement.
If you apply the translatetransform to an element before a rotate, skew or scale transform then the CenterX and CenterY will be taken in relation to the position of the element set by the translatetransform rather than the original position. This is because the element is being moved to a new position then being re-drawn rather than just being re-drawn.)
Even though I have set CenterX and CenterY to 20 in the rotatetransfom, when the skewtransform is applied the button is no further to the right along the x-axis and is moved the 10 points lower along the y-axis because the properties are taken from the original position of the button.
I have posted up some working examples of Transforms where you can change some of the properties of a Transform and see how they look and work to go along with the posts that I have done for RotateTransform, SkewTransform, ScaleTransform, TranslateTransform and the TransformGroup.
The page with the working examples can be found here.
In a way this could be a continuation of my look into transitions in Silverlight because what this post is going to cover is a perspective transform.
Silverlight does not have a toolkit for 3-D drawing but this perspective transform gives you the opportunity to simulate 3-D. Like the other transforms it takes the existing element and changes how it is drawn only this one makes it look like it is on a 3-D surface.
1. Setting up the Project.
For this project I have created a Silverlight 3 application hosted in an ASP.NET web site and added a small image to the ClientBin directory.
The silverlight application itself consists of a 400x400 point UserControl with a Grid as its root layout container. In the middle of the Grid I have placed the image.
2. The PlaneProjection.
Similar to how you add a Transform to an Element you must put the planeprojection inside the projection property.
Once you have added opening and closing tags for the property, you can define the planeprojection.
The planeprojection class lets you rotate an element along three axes*. The x, y and z.
(* I will admit that I did have to look up what the plural of axis was. Axes still doesn’t look right but I know it is.)
The way the element rotates around the axis gives the illusion of 3-D space. I have used and image in this example, but you can apply a planeprojection to any element.
The x-axis runs horizontally through the middle of the element which makes the top of the element seem close or further away depending on the rotation angle.
The y-axis runs vertically through the middle of the element and swings the left or right of the element nearer or further depending on the rotation angle.
The z-axis rotates the element in the same way that the RotateTransform does. It will rotate the element around a central set of coordinates.
3. Rotating on the x, y and z axes.
To use the planeprojection you only need to define on rotation angle, though depending on effect you wish to achieve you may want to set more than one property.
By setting a value for the RotationX property give the perception of the top or the bottom of the element angling towards you. If you use a positive number then the top appear closer to you and a negative number makes the bottom look closer.
Setting the angle of rotation to 45 degrees cause the image to rotate over the x-axis at the default centre point which is half way down the y-axis.
I’ll go over rotation centre points in a bit.
The same idea works with rotating around the y-axis.
The left of the image now appears closer as the image is rotated at a point half way along the x-axis.
As I mentioned earlier, setting a value for rotationz is just like using a RotateTransform. The element is rotated around a central point.
Without defining any other properties the element is rotated around the default centre points of all three axes. In this case the image is rotated around its centre.
4. The CenterOfRotation.
The CenterOfRotation determines the point along any axis which the projection is applied. The values for the x and y range, generally, from 0 to 1 starting at the top left corner of the element and moving down and to the right. The value for the z-axis starts at 0 which is the defined position of the element.
By default the values for CenterOfRotationX and CenterOfRotationY is 0.5 or half way along the x-axis and y-axis. The default value of CenterOfRotationZ is 0. With CenterOfRotationZ, positive numbers are in front of the element and negative numbers are behind it.
You need to remember when you want to change the rotation centre point you don’t change the centre of rotation on the same axis that you are rotating around. You change the centre on the opposing axis. Setting the centre of rotation on the same axis as the one you are rotating around has no effect.
Setting the value of CenterOfRotationY to .25 the image now rotates only a quarter down the height and gives the impression that it is further away. The blue line in the screen shot below shows where the centre of rotation now is in comparison to the center of the image.
The same as you make set the centre of rotation along the y-axis for rotating around the x-axis you change the value of CenterOfRotationX to alter where the element rotates around the y-axis.
The blue line in the screen shot shows where the image is now rotating around the y-axis giving the illusion that the right side of the image is closer.
To change where the element is rotated along the z-axis you can set a point along one, or both, the x-axis or y-axis.
The intersection of the blue lines show where the image is being rotated from.
5. The GlobalOffset.
The GlobalOffset property is used to move the element you are applying the projection to along any or all of the x, y or z axes.
The important fact to remember about this property is that it is applied to the element before the projection is applied so your element is moved along the defined axis then rotated. This statement will make more sense when the LocalOffset property is covered later.
Using the XAML below, the image is moved 25 points to the right then rotated 45 degrees on the x-axis.
Setting a value for the globaloffsetx property makes the element move closer to the right.
The default value for the globaloffset property is 0. For the x-axis and y-axis 0 is located at the top left of the element.
Using positive values moves the image down and to the right, while negative numbers would cause a movement up and to the left.
The globaloffsetz property gives the illusion of the image being either closer or further away from you. Negative values move the image back away from the front and positive numbers move it in closer.
I used an exaggerated value of 200 along the z-axis to bring the image closer as you can see in the following screen shot.
6. The LocalOffset.
The LocalOffset property also moves the element along the three axes.
The difference between the two properties, the GlobalOffset and LocalOffset, is when they are applied to the element.
As was mentioned earlier the globaloffset is applied before the projection. The localoffset property is applied after the projection.
What does this mean?
Let’s examine the XAML below.
The image is going to be rotated 90 degrees on the z-axis which will basically turn it on its side, then the image will move 50 points along the y-axis.
The screen shot below shows this happening.
The image rotated and moved to the right, but was this supposed to happen?
The answer is yes.
Even though you may think that the image moved along the x-axis, which we know from earlier follows a horizontal line, it actually followed the y-axis as we told it to in the XAML.
Why is this?
It is because as I mentioned the localoffset properties are applied to the element after the projection.
The next screen shot shows where the localoffset axes for x and y are. Though I have not added it the z-axis for the localoffset would be on a line from the lower right corner of the image of the Opera House to the lower right corner of the screen shot.
7. Putting it all together.
Now you can set as many properties as you want for the PlaneProjection and give a 3-D look to your elements.
Over the last few years, SEO has grown into an expertise all its own. Everyone wants their sites to be “SEO friendly”, or optimized for search engines. Until now, creating dynamic sites using ASP.Net web forms that were SEO friendly was a daunting and tedious task.
Now, in ASP.Net 4.0 and the introduction of System.Web.Routing namespace, creating SEO friendly sites just became very easy. There is a lot of buzz around MVC, not a new concept, but new’ish to ASP.Net. Currently, MVC is in version 2.0 and for those that don’t know what MVC is or what it stands for, MVC is an acronym for “Model View Controller”. While this mini tutorial is not about MVC at all, System.Web.Routing was ported to it’s own library from the MVC framework so that the benefits of routing can be used in ASP.Net web forms too.
So, why is routing cool? Take a look at the following url’s:
/store/product.aspx?catid=43&prodid=123&color=red&prod=notebook&desc=windows7
vs.
/store/43/123/red/windows7/notebooks
I don’t need to ask which URL is more SEO friendly or more descriptive. Before the introduction of the new routing capabilities, URL re-writing was typically used to redirect users from friendly (display) URL’s to a handler. I won’t get into how the “old” way was done, but I will show you how to achieve this with routing.
System.Web.Routing has many properties, methods, etc. available to the user. You can perform routing on a page or define routes globally using the global.ascx file.
It works by creating a routing table, routing dictionaries and declaring a handler/form for each route. You could use one file to handle all routes, but this would likely get very messy, very fast.
For this example, we are only going to have a single route defined that can handle all articles we will publish. The first thing we need to do is create a new web site that targets the 4.0 framework. Next we will need to open the global.ascx file and add a method that will register our routing table, as well as calling this method in our application_startup method.
Inside the global.ascx file, add a reference to System.Web.Routing and add a call to RegisterRoutes method we will create later inside your Application_Start method:
<%@ Import Namespace="System.Web.Routing" %>
void Application_Start(object sender, EventArgs e)
{
// register rout mapping tables
RegisterRoutes(RouteTable.Routes);
} public static void RegisterRoutes(RouteCollection routes) { routes.MapPageRoute("ArticleRoute", "articles/{aid}/{colid}/{artname}", "~/news/default.aspx", false,
new RouteValueDictionary {
{ "aid", "1" },
{ "colid", "1"},
{ "artname", "invalid-article" }},
new RouteValueDictionary {
{ "aid", "[0-9]{1,8}" },
{ "colid", "[0-9]{1,8}" } }); }
**Notice in the above snippet, we not only defined our route and parameters, but also constraints for our parameters in our second, but optional RouteValueDictionary object. More on this later.
Now, once we have our routes defined and registered, we need to create our form that will handle all requests that map to our article route.
Go ahead and create a new folder and add a new web form (default.aspx). Now that we have our form built, we need to add logic to the forms to get the parameters from the routed request so we can use them later as parameters to fetch data, manipulate stuff or load other dynamic controls.
Earlier, I wrote that accessing these parameters could be “as simple, if not more simple and more secure…” Lets look at how to access these parameters.
protected void Page_Load(object sender, EventArgs e)
{
//Using a loop, we can grab all the key-value-pairs that is accessible via
//Page.RouteData.Values collection.
foreach (KeyValuePair<string, object> kvp in Page.RouteData.Values)
{
lblAllValues.Text += "Key: " + kvp.Key + " Value: " + kvp.Value + "<br />";
} //Grabbing the routing values using a loop might not be too useful.
//We will access them individually.
Int32 articleid = Convert.ToInt32(RouteData.Values["aid"]);
Int32 columnid = Convert.ToInt32(RouteData.Values["colid"]);
string articlename = RouteData.Values["artname"].ToString();
}
Ok, we can see that this is at the very least, as simple as grabbing values from the query string. So, how is this more secure? Take a look at the routes we defined earlier. The MapPageRoute takes a set of parameters:
If we choose to enter constraints, this means the parameters must fall within an acceptable range. If they don’t, it is assumed it is a bad path, and a 404 will be generated. Thus, disallowing bad parameters from reaching the file handler. This has it’s pro’s and con’s. Pro's: initial rigor, or first step validation. Cons: the handler can’t make a provision for the disallowed parameters as it’s never hit.
What if we want to enforce some constraints for our parameters, but not for all? No problem. You can define a constraint for one, all, some or none of your parameters – it’s pretty flexible and should accommodate almost any situation.
Can you use both query string and routing values? Yes you can. Below is an example of how you would make provisions using a wild card “*” character in your route definition parameters.
/*Article routing with wildcard to handle additional qs params*/
routes.MapPageRoute("ArticleRoute", "articles/{aid}/{colid}/{artname}/{*qsparams}", "~/news/default.aspx", false,
new RouteValueDictionary {
{ "aid", "1" },
{ "colid", "1"},
{ "artname", "invalid-article" }},
new RouteValueDictionary {
{ "aid", "[0-9]{1,8}" },
{ "colid", "[0-9]{1,8}" } });
}
Notice the additional information we included in our mapping {*qsparams} now our path will match and be routed to the handler with or without additional information in the querystring.
One last note, if you have routes that are similar, the first route that is matched is the one that is used. This means you should have clearly defined routes and in order of activity. For example, if your "articles" page is accessed most often, it should be the first route added. Conversely, a page that is visited the least, should be added last.
Attached is a sample application.
Element binding is the process of setting up a relationship between the value of a property of one element to the property of another element. Once the properties are bound you can alter the properties of one element from the other.
If you have been following this series on Beginning Silverlight, and visited the example pages for Brushes, Transforms or Plane Projection then you have seen element binding in action. Very little code behind was used on any of the examples and As a matter of fact there is no code behind used in the Plane Projection. All the movement of the image is done with element to element binding.
1. Setting up the Project.
For this example I am starting with a 400x400 grid with four rows. Three of the rows I have defined a set height to and the other will take up the remaining space.
Into the second row I had defined a rectangle and added a slider to each of the last two rows. Each of the three elements have had a Name set in their definition as that will be required for binding.
In the post on Styles, binding of another sort was introduced, binding to a StaticResource.
When you use the curly braces {} in your XAML markup you are binding to whatever is defined between the braces.
In this example I have defined a brush in the resources of the usercontrol then bound the fill property of the rectangle to that brush. Being a single colour the fill does not need to be set this way, rather it is has been done as a refresher on binding to staticresource.
There are three ways that you can set the relationship between elements to have the data flow. There are OneWay, TwoWay and OneTime. For this post I am only going to look at OneWay and TwoWay binding.
2. OneWay Binding.
OneWay binding means that data flows in one direction from one element to the other only. No data is passed back.
For element to element binding you need to include three bits of information. You need to have a Path, Mode and ElementName. For this example the value of one of the sliders is going to be used to change the height of the rectangle.
Instead of defining an explicit height in the XAML of the rectangle the Binding syntax is used.
You can see in the following XAML that the definition for the height property starts with the curly brace and the keyword Binding. Next is the property that the other element, the slider, that the height is being bound to which is the Value of the slider. This is the Path. I didn’t have to but could have also defined the path like:
Path=Value
Using the Path keyword is not required. Next the mode is set to OneWay, and lastly the name of the slider is set as the source object.
When the project is run the rectangle takes the current value of the slider, in this instance 10 because when no value is defined for a slider the default value is the minimum, for its height as well as the XAML defined width.
Moving the thumb of the slider to the far right causes the rectangle to grow, as the slider moves, to the maximum of the slider (in this example the maximum is 300 points).
The same ides is used for the width of the rectangle.
The only difference between the binding used for the height and width is the source object. The width property is set to the value of the Width slider.
When the project is run the height and width of the rectangle is set to the value of the respective sliders. Since no value was defined for the sliders the default, or minimum, value is used for the height and with giving a 10 point by 10 point rectangle.
Now when the thumb of the width slider is moved the rectangle changes its width accordingly.
With both the height and width of the rectangle bound you can control the size of the rectangle using both sliders.
3. TwoWay Binding.
TwoWay binding means that data will flow both to a bound element as well as from a bound element which causesthat element to act as a source object for another bound element.
To show this I have added a StackPanel into the first row of the Grid and put two TextBlocks and two TextBoxes into the StackPanel.
The height and width of the rectangle will be displayed in their respective textboxes.
Nothing is displayed in the textboxes because the Text property of the boxes has not been bound to anything as of yet.
The text property is going to be bound to the value of the height and width sliders so the XAML markup to bind the text to the value of the slider is added to the definition of the boxes using the slider name as the source object and setting the sliders value as the path. The mode is set to TwoWay because the textboxes are not only going to show the height and width of the rectangle but also be also used to set the height and width.
Now when the project is run the rectangle is set to the default values of the sliders and those values are displayed in the textboxes.
Manipulating the sliders causes the rectangle to change size and the values are displayed in the height and width textboxes.
Entering a number into the textbox however does not change the size even though the mode is set to twoway. This is because no element has been bound to receive data from the textboxes.
To make it so that when the user enters an amount into one of the textboxes it causes the value of the slider to change, which will make the height or width of the rectangle to change, you need to bind the value of the slider to the text property of its respective textbox.
The path is set to the text property and the source object is the corresponding textbox. The mode can be set to either OneWay or TwoWay, but there is a subtle difference as to how the binding works.
Setting the mode to TwoWay, as I have done below, if the user changes the number in the textbox the value of the slider changes as the user enters a new number. If the mode is set to OneWay, if the user enters another number into the textbox, the value of the slider does not change until the textbox with the new number loses focus.
With the mode set to twoway for both the textboxes and the sliders the text in the textbox changes to match the value of the slider as the sliders thumb is moved, and the sliders thumb moves as a new number is entered into the textbox.





































































































































































































