Sunday, 4 April 2010

Dynamic User Controls – Part 3 – Using a repeater

Continuing on from my previous posts (parts 1 and 2) this post will detail how to use a repeater to add a textbox control dynamically.

First off we will create a new tab that will contain a button control and a repeater that will contain a placeholder control


The idea are working with is the following. The placeholder will contain only 1 control at a time, be a composite user control or in this example a textbox control. We will bind a generic list of strings to the repeater and using the ItemCreated event of the repeater, we will program it to create a textbox and put the contents of the string item into the text property of the textbox.

We will also create a page property that returns a generic list of strings. This will be got from the repeater but looping through each item in the Items collection and finding the textbox in the placeholder control and getting its text property. Each time we want to add a new textbox, we will use this page property to get all the current values and then add a new blank string to this list. After we have done that, we will rebind the repeater with the new list. By using this method to create our textboxes, we can store the values easily and manage state easily as well.



So now the page property

What we are doing here, is firstly creating a new list on line 5. Then we are looping through all the RepeaterItems in the Items collection of the Repeater. In the item, we are finding the textbox that we have added. We do this by using the FindControl method of the RepeaterItem to find the specified placeholder control and then accessing its Controls collection and casting that object as a textbox control. We dont need to cast the placeholder control because it inherits from the Control object which has a Controls collection. Once we have that textbox we add the value of the Text property to our list. Once we have looped through all the RepeaterItems we will return the list.

Now to the OnClick event handler of the button which will add a new textbox

So we first create a new list called currentData and assign it to the value of CurrentTextBoxData which is the page property we created just before. We then add a blank string to the list. Once we have done that, we set the repeater’s data source to the new list and then databind it.

Why do we create a new list and what doesn’t the CurrentTextBoxData property have a setter?. The answer to both these questions is the following. Firstly we are using the repeater as a date store to store the current values in the textbox. Each time we want to add to it, we should get a copy of the current values and add the new value to this copied list. Finally we will replace the current values with the new copy of the values. So in this way, there is no need for a setter per se because the databind event acts as the setter since it places all the values in the repeater.



We will continue with the ItemCreated event of the repeater. You will need to either manually add the event to the repeaters declaration in the ASPX page or add it in the Page.OnInit entry in the code behind.

Firstly, we cast the DataItem to a string. We know this is a string because that is what are binding to the repeater control. We then create a new instance of a textbox control and set its text property to the string in the DataItem. Now we create a placeholder and assign it to the placeholder in the repeater item using the FindControl method. We then add our newly created textbox to the placeholder. This how we dynamically create our controls.

Running this will now allow you to click the button and that will add a new control. You can edit the values of the textboxes and they will survive postback because each time we need to create new ones, we get the current values and then recreate them all again.

The next post will deal with adding dynamic databound user controls and also how to remove dynamic controls as well as bubbling events up from your user control to be handled by the repeater.

The code bits for all these posts can be found in the first post here

Friday, 2 April 2010

Dynamic User Controls – Part 2 – The Wrong Way

Following on from my session intro post, this post will deal with the “wrong” way to add controls to the page. Its wrong in the traditional sense, it just doesn’t provide as much control as you would like. Also it makes it difficult to manage the number of controls and events on the page. So lets get into it. Some prerequisites. I am using the AJAX Control Toolkit for my demos. Specifically I am using the AJAX Tab control to show off the demo. If you are not using one of the versions I uploaded, you will need this toolkit to follow the code I will be writing. Or you can just not use it and take out the tabContainer code :) Starting off, I have the standard Default.aspx page with a ScriptManager control on it. Also on the page I have an instance of the AJAX Control Toolkit TabControl. In the TabControl I have one tabPanel with an ASP PlaceHolder control and an ASP Button Control
<cc1:TabPanel ID="tabStart" runat="server" HeaderText="Start">
<ContentTemplate>
<asp:PlaceHolder ID="phControls" runat="server" />
<br />
<asp:Button ID="btnAddControl" runat="server" Text="Add a new text box"
CausesValidation="false" OnClick="AddDemoControl"/>
</ContentTemplate>
</cc1:TabPanel>

In the code behind of the page I have the Page_Load event and the event handler for the OnClick event of the ASP button.
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack) return;
//Add 2 new textboxes to the specified placeholder
phControls.Controls.Add(new TextBox());
phControls.Controls.Add(new TextBox());
}

protected void AddDemoControl(object sender, EventArgs e)
{
phControls.Controls.Add(new TextBox());
}

When the page is loaded for the first time, 2 textbox controls are added to the page. When you click the button, only one textbox is shown. This is because the check to see if the page is a postback stops the first two textboxes from being loaded. Removing this line will mean that when you click the button three textboxes are shown on screen.

If you keep clicking the button, only three textboxes will be shown. This is because the controls do not survive the postback event and so are recreated new every time. So in this way this is one of the reasons I will use the repeater model to create dynamic controls.

How to do this using a basic textbox control will be covered in the next post.

Dynamic User Controls – Part 1 – Session Intro

I recently gave three talks around Ireland on this topic for the Irish Microsoft Technology User Group (MTUG). I travelled to Derry, Dublin and Cork over three days and met some great folks. I was also very lucky to be presenting on the same night as Adam Kinney from Microsoft which was an excellent chance for me to get some news on Silverlight and the new bits from MIX10. A big thanks to Alan Bradley, David Gargan and Joe Gill on the MTUG side and Martha Rotter and Enda Flynn from Microsoft for facilitating this and also making sure I got to where I was supposed to go.

As promised to all those who attended my talks I am posting the session as a series of blog posts along with the bits from the sessions. The bits can be downloaded in 3 versions

If you are using the Visual Studio 2010 RC version make sure to download the Designer patch for the RC. This version will also work with the Beta 2 version of Visual Studio 2010.

So on with the speaker bits. I am not putting the PowerPoint online as it does not contain anything other than pictures and some text and its pretty useless without the speaker notes. So I am going to instead to put the speaker notes in this blog post with the PowerPoint slides as images.

WhyDoYouWantDynamicControls

The first question you should be asking is why do you want user controls in the first place. And the answer is usually one of the following three options

  • You don’t know the number or type of controls that you will need until runtime. This is possibly the most common reason to use dynamic controls.
  • You have a large number of the same type of control that you need to add to the application and you don’t want to spend the time manually putting them onto the design surface. Most people will be familiar with this because I doubt you have ever manually created 100 list items in a DataList for example
  • And finally its because of an architectural decision such as a custom server control and you have no choice.

 

 

The next question is what is the different between static and dynamic controls. Well firstly static controls StaticVsDynamicControls 

  • Can be added to the design surface at design time
  • They can be programmed against with intellisense because they are in the .designer.cs file
  • And finally they survive post back and the page life cycle.

On the other hand dynamic controls

  • Dynamic controls are added to the page control tree at runtime
  • They cannot be programmed against using intellisense in the traditional way. You can declare an object of the type of control and bring it to your instance of the control and program against it in that way
  • Dynamic controls do not survive the post back unless you give them a place to stay. And that is the crux of the problem involving dynamic controls.

PostBack

 

Now that we know what the issue is how do we solve it. Normally when you are using dynamic controls you add the controls to a placeholder and this works ok to a point. A better way of doing it is to use a repeater with a placeholder in the ItemTemplate and use custom methods of the ItemCreated and ItemCommand events. There are a few good reasons for this.

  • You can databind your list to your repeater allowing to quickly create a lot of controls
  • You can make your controls have databinding properties.
  • You can use the fact that the repeater is IEnummerable to get the information in and out
  • The ItemCommand event allows you to handle events from your controls
  • And finally it gives you a way to easily store state by using the repeater.

 

 

So that was the intro part of the session. As you can see I didn’t use a lot of time in PowerPoint because I believe that developers learn better from seeing the code rather than from a slide deck. The next posts will be all on the code parts of the sessions.

If you want to learn more about the whole viewstate relationship with dynamic controls you can read Dave Reed‘s excellent blog posts on the subject. I would like to take this chance to thank him for his kind permission in allowing me to use some of his material for my sessions.

Setting up Visual Studio 2010 for presentations

Lately I have been giving a couple of talks and they are mainly code demonstrations. So you really need to make sure you have your Visual Studio set up correctly to handle the different way you write code when you are presenting as compared to normal development.

Some essential things.

  • Increase the size of your font
    • This is possibly the single biggest thing (pardon the pun) that you can do to increase the takeup and attendee satisfaction is to increase the size of your font to a decent size that works well on projector screens. Thanks to Scott Hanselman who suggested in his blog post that you should use Lucida Console 14 to 18pt and bolded. Believe me it works and allows your audience to actually read your code.
    • You can also use the command line devenv /fs 16 to increase all the font sizes in the menus to 16 for example. You can reset it back using devenv /fs 8 . But you don’t need to do this if you aren’t showing off any menu options.
  • Adjust your IDE color
    • I know i know, your IDE color is your own. But I am fan of the plain standard white background with the standard keyword colors. Its just a bit easier. However if you do find a color scheme that works on a large screen to a diverse audience please do let me know
  • Use snippets
    • Snippets are your best friend. Use them. You don’t have to use them for everything but if you are doing a decent amount of code its helps you if you make it a mistake. And remember the keystrokes CTRL+K followed by CTRL+X to bring up the snippets menu.
    • There are a number of snippet designer tools such as Snippet Designer which allows you to to create your snippets in the IDE. Make sure to add descriptions to your snippets so you can see what they do without have to read the name.
    • I also create folders for my demo snippets and in the title I number them so I can find them easily. In the last set of demos, I had them labeled with numbers that corresponded to the section I was demonstrating in.

Now some additional tools for Visual Studio 2010. There is an excellent free tool called Custom Intellisense Presenter which allows to show the intellisense popup in a higher more visible which for your audience is very handy as they can read and hopefully understand while you are coding. Also with the snippets it will display your description which will help you when you are coding.

There are also custom zoom tools which can be found here and also the very handy windows key + (+) key to zoom in if you don’t find anything that works for you.

And finally make sure your code compiles :)