Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Dynamically Generating Controls in WPF and Silverlight

Pete Brown - 08 December 2010

Some of the Windows Forms developers I've spoken to have said that one thing they want to learn is how to dynamically create controls in WPF and Silverlight. In this post I'll show you several different ways to create controls at runtime using Silverlight 4 and WPF 4.

First, we'll start with how to create controls in XAML. From there, we'll move to dynamically-loaded XAML before we take a look at using the CLR object equivalents.

Creating Controls at Design Time in XAML

Creating controls using the design surface and/or XAML editor is definitely the easiest way to create your UI. You can use Expression Blend or Visual Studio, depending upon how creative you want to be. If you want a more dynamic layout, you can hide and show panels at runtime.

Here's an example layout:

<Grid Margin="10">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
            
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <TextBlock Text="First Name"
                Height="19"
                Margin="0,7,31,4" />           
    <TextBox x:Name="FirstName"
                Margin="3"
                Grid.Row="0"
                Grid.Column="1" />
            
    <TextBlock Text="Last Name"
                Margin="0,7,6,3"
                Grid.Row="1"
                Height="20" />
    <TextBox x:Name="LastName"
                Margin="3"
                Grid.Row="1"
                Grid.Column="1" />


    <TextBlock Text="Date of Birth"
                Grid.Row="2"
                Margin="0,9,0,0"
                Height="21" />
    <sdk:DatePicker x:Name="DateOfBirth" 
                    Margin="3"
                    Grid.Row="2"
                    Grid.Column="1" />


    <Button x:Name="SubmitChanges"
            Grid.Row="3"
            Grid.Column="3"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Margin="3"
            Width="80"
            Height="25"
            Content="Save" />
</Grid>

That markup creates a layout that looks like this in Silverlight:

image

Or, if you're using WPF, like this:

image

(note that you'll need to remove or remap the "sdk" prefix when using this XAML in WPF, as the date control is built-in)

Once you're familiar with working in XAML, you can easily modify the process to load the XAML at runtime to dynamically create controls.

Creating Controls at runtime using XAML strings

In Silverlight, this block of code in the code-behind creates the same controls at runtime by loading the XAML from a string using the System.Windows.Markup.XamlReader class. This class exposes a Load method which (in Silverlight) takes a well-formed and valid XAML string and returns back a visual tree

public MainPage()
{
    InitializeComponent();

    Loaded += new RoutedEventHandler(MainPage_Loaded);
}

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    CreateControls();
}


private void CreateControls()
{
    string xaml =
    "<Grid Margin='10' " +
        "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' " + 
        "xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' " + 
        "xmlns:sdk='http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk'>" + 
        "<Grid.ColumnDefinitions>" +
            "<ColumnDefinition Width='100' />" +
            "<ColumnDefinition Width='*' />" +
        "</Grid.ColumnDefinitions>" +

        "<Grid.RowDefinitions>" +
            "<RowDefinition Height='Auto' />" +
            "<RowDefinition Height='Auto' />" +
            "<RowDefinition Height='Auto' />" +
            "<RowDefinition Height='*' />" +
        "</Grid.RowDefinitions>" +

        "<TextBlock Text='First Name' Height='19' Margin='0,7,31,4' />" +
        "<TextBox x:Name='FirstName' Margin='3' Grid.Row='0' Grid.Column='1' />" +

        "<TextBlock Text='Last Name' Margin='0,7,6,3' Grid.Row='1' Height='20' />" +
        "<TextBox x:Name='LastName' Margin='3' Grid.Row='1' Grid.Column='1' />" +

        "<TextBlock Text='Date of Birth' Grid.Row='2' Margin='0,9,0,0' Height='21' />" +
        "<sdk:DatePicker x:Name='DateOfBirth' Margin='3' Grid.Row='2' Grid.Column='1' />" +

        "<Button x:Name='SubmitChanges' Grid.Row='3' Grid.Column='3' " +
            "HorizontalAlignment='Right' VerticalAlignment='Top' " +
            "Margin='3' Width='80' Height='25' Content='Save' />" +
    "</Grid>";


    UIElement tree = (UIElement)XamlReader.Load(xaml);

    LayoutRoot.Children.Add(tree);
}

Note that I needed to add the namespace definitions directly in this XAML. A chunk of XAML loaded via XamlReader.Load must be completely self-contained and syntactically correct.

The WPF XamlReader.Load call is slightly different as it has no overload which would take a string. Instead, it takes an XmlReader as one form of parameter:

StringReader stringReader = new StringReader(xaml);
XmlReader xmlReader = XmlReader.Create(stringReader);

UIElement tree = (UIElement)XamlReader.Load(xmlReader);

LayoutRoot.Children.Add(tree);

 

This technique also works for loading chunks of XAML from a file on the local machine, or as the result of a database query. It's also helpful for enabling the use of constants (like the extended color set) that are recognized by XAML parser in Silverlight, but not from code.

The more typical approach to dynamically creating controls, however, is to simply use the CLR objects.

Creating Controls at runtime using Code and CLR Objects

Everything you do in XAML can also be done from code. XAML is a representation of CLR objects, rather than a markup language that abstracts the underlying objects. Creating controls from code tends to be more verbose than doing the same from XAML. However, it is a familiar approach for Windows Forms developers, and a great way to handle dynamic UI.

private void CreateControlsUsingObjects()
{
    // <Grid Margin="10">
    Grid rootGrid = new Grid();
    rootGrid.Margin = new Thickness(10.0);
            
    // <Grid.ColumnDefinitions>
    //   <ColumnDefinition Width="100" />
    //   <ColumnDefinition Width="*" />
    //</Grid.ColumnDefinitions>

    rootGrid.ColumnDefinitions.Add(
        new ColumnDefinition() { Width = new GridLength(100.0) });
    rootGrid.ColumnDefinitions.Add(
        new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });

    //<Grid.RowDefinitions>
    //  <RowDefinition Height="Auto" />
    //  <RowDefinition Height="Auto" />
    //  <RowDefinition Height="Auto" />
    //  <RowDefinition Height="*" />
    //</Grid.RowDefinitions>

    rootGrid.RowDefinitions.Add(
        new RowDefinition() { Height = GridLength.Auto });
    rootGrid.RowDefinitions.Add(
        new RowDefinition() { Height = GridLength.Auto });
    rootGrid.RowDefinitions.Add(
        new RowDefinition() { Height = GridLength.Auto });
    rootGrid.RowDefinitions.Add(
        new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });

    //<TextBlock Text="First Name"
    //           Height="19"
    //           Margin="0,7,31,4" />

    var firstNameLabel = CreateTextBlock("First Name", 19, new Thickness(0, 7, 31, 4), 0, 0);
    rootGrid.Children.Add(firstNameLabel);

    //<TextBox x:Name="FirstName"
    //         Margin="3"
    //         Grid.Row="0"
    //         Grid.Column="1" />

    var firstNameField = CreateTextBox(new Thickness(3), 0, 1);
    rootGrid.Children.Add(firstNameField);

    //<TextBlock Text="Last Name"
    //           Margin="0,7,6,3"
    //           Grid.Row="1"
    //           Height="20" />

    var lastNameLabel = CreateTextBlock("Last Name", 20, new Thickness(0, 7, 6, 3), 1, 0);
    rootGrid.Children.Add(lastNameLabel);

            
    //<TextBox x:Name="LastName"
    //         Margin="3"
    //         Grid.Row="1"
    //         Grid.Column="1" />

    var lastNameField = CreateTextBox(new Thickness(3), 1, 1);
    rootGrid.Children.Add(lastNameField);


    //<TextBlock Text="Date of Birth"
    //           Grid.Row="2"
    //           Margin="0,9,0,0"
    //           Height="21" />

    var dobLabel = CreateTextBlock("Date of Birth", 21, new Thickness(0, 9, 0, 0), 2, 0);
    rootGrid.Children.Add(dobLabel);

    //<DatePicker x:Name="DateOfBirth"
    //            Margin="3"
    //            Grid.Row="2"
    //            Grid.Column="1" />

    DatePicker picker = new DatePicker();
    picker.Margin = new Thickness(3);
    Grid.SetRow(picker, 2);
    Grid.SetColumn(picker, 1);
    rootGrid.Children.Add(picker);

    //<Button x:Name="SubmitChanges"
    //        Grid.Row="3"
    //        Grid.Column="3"
    //        HorizontalAlignment="Right"
    //        VerticalAlignment="Top"
    //        Margin="3"
    //        Width="80"
    //        Height="25"
    //        Content="Save" />

    Button button = new Button();
    button.HorizontalAlignment = HorizontalAlignment.Right;
    button.VerticalAlignment = VerticalAlignment.Top;
    button.Margin = new Thickness(3);
    button.Width = 80;
    button.Height = 25;
    button.Content = "Save";
    Grid.SetRow(button, 3);
    Grid.SetColumn(button, 1);
    rootGrid.Children.Add(button);

    LayoutRoot.Children.Add(rootGrid);
}

private TextBlock CreateTextBlock(string text, double height, Thickness margin, int row, int column)
{
    TextBlock tb = new TextBlock() 
        { Text = text, Height = height, Margin = margin };
    Grid.SetColumn(tb, column);
    Grid.SetRow(tb, row);

    return tb;
}

private TextBox CreateTextBox(Thickness margin, int row, int column)
{
    TextBox tb = new TextBox() { Margin = margin };
    Grid.SetColumn(tb, column);
    Grid.SetRow(tb, row);

    return tb;
}

You'll see the code is only slightly more verbose when expanded out. The two helper functions help minimize that. In the code, I create the entire branch of the visual tree before I add it to the root. Doing this helps minimize layout cycles you'd otherwise have if you added each item individually to the root.

I tend to put any UI interaction inside the Loaded event. However, you could place this same code inside the constructor, after the InitializeComponent call. As your code gets more complex, and relies on other UI elements to be initialized and loaded, you'll want to be smart about which function you use.

Handling Events

If you want to handle events, like button clicks, you'd do that like any other .NET event handler:

{
    Button button = new Button();
    ...
    button.Click += new RoutedEventHandler(button_Click);

    LayoutRoot.Children.Add(rootGrid);
}

void button_Click(object sender, RoutedEventArgs e)
{
    ...
}

Creating controls from code doesn't mean you lose the valuable ability to data bind. In some cases, especially where the binding source is hard to reference from XAML, binding is easier in code.

Binding Dynamically Created Controls

We haven't used any binding yet, so we'll need to create a binding source. For that, I created a simple shared project that targets Silverlight 4. It's a Silverlight class library project and is used by both the WPF and Silverlight examples. Remember, to use it from WPF 4 (without any additions), you'll need to use a file reference to the compiled DLL, not a project reference.

Inside that project, I created a single ViewModel class named ExampleViewModel.

public class ExampleViewModel : INotifyPropertyChanged
{
    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; NotifyPropertyChanged("LastName"); }
    }

    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; NotifyPropertyChanged("FirstName"); }
    }

    private DateTime _dateOfBirth;
    public DateTime DateOfBirth
    {
        get { return _dateOfBirth; }
        set { _dateOfBirth = value; NotifyPropertyChanged("DateOfBirth"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Inside the code-behind (this is a demo, after all) of the Window (or Page), initialize the viewmodel class:

private ExampleViewModel _vm = new ExampleViewModel();

public MainWindow()
{
    _vm.LastName = "Brown";
    _vm.FirstName = "Pete";
    _vm.DateOfBirth = DateTime.Parse("Jan 1, 1910");

    InitializeComponent();

    ...
}

Once that is done, we can create an example binding. I'm going to use the First Name TextBox and set up two-way binding with the FirstName property of the ExampleViewModel instance.

var firstNameField = CreateTextBox(new Thickness(3), 0, 1);
Binding firstNameBinding = new Binding();
firstNameBinding.Source = _vm;
firstNameBinding.Path = new PropertyPath("FirstName");
firstNameBinding.Mode = BindingMode.TwoWay;
firstNameField.SetBinding(TextBox.TextProperty, firstNameBinding);          

rootGrid.Children.Add(firstNameField);

The same approach to expressing binding also works in XAML. It's just that we have a binding markup extension that makes the process easier.

One thing that tripped me up in this example was I passed in TextBlock.TextProperty to the SetBinding call. That's a valid dependency property, so it compiles just fine. In WPF, that fails silently, even when you have verbose binding debugging turned on. In Silverlight, it throws a catastrophic error (without any additional information). That catastrophic error made me look more closely at the call, ultimately leading to the fix.

To bind controls added using dynamically-loaded XAML, you'll need to provide a valid Name to each control you want to reference, then use FindName after loading to get a reference to the control. From there, you can using the Binding object and SetBinding method. Of course, you can also embed the binding statements directly in the XAML if you wish to do a little string manipulation.

Summary

So, we've seen that there are three different ways you can display controls in Silverlight and WPF.

  • Use the design surface / XAML Editor / Blend and create them prior to compiling
  • Load XAML at runtime
  • Use CLR Objects at runtime

Each way is useful in different scenarios, and also has different performance characteristics. XAML parsing is surprisingly efficient and the XAML can be stored in a large text field in a single row in a database or as a loose file on the file system, for example.

For additional information on the layout system and the visual tree, please see the following

The attached zip file contains source for both Silverlight 4 and WPF 4.

             

Source Code and Related Media

Download /media/73013/petebrown.dynamiccontrols.zip
posted by Pete Brown on Wednesday, December 8, 2010
filed under:              

52 comments for “Dynamically Generating Controls in WPF and Silverlight”

  1. Petesays:
    @Se

    Give the control a name inside the XAML string.

    Then, use FindName to get a reference. Something like:

    var firstNameField = (TextBox)FindName("FirstNameField");

    then you can use normal .NET event syntax:

    firstNameField.LostFocs += new ....

    Pete
  2. Jonathansays:
    This reminds me a lot of some of the discussions I have had with a lot of developers who are looking to jump into Silverlight. I took a lot of these concepts over various projects and integrated into a framework that I have put up on Codeplex opus.codeplex.com.(shameless plug)

    But beside that I think this is a great article and all developers who are moving to SL and WPF should read so they can get a better understanding of how controls are built and bound.

    Great Article!
  3. Zbigniewsays:
    Our small Silverlight-ERP is written using only dynamically created controls with "Creating Controls at runtime using Code and CLR Objects" approach described is this article. This model has some advantages, but has some disadvantages, too. If I would begin this project again, I would probably choose the standard, static approach …
  4. PilotBobsays:
    Great article. I am doing a lot of this in our current app. The one thing I am not fond of is that I have all of the control building code (using CLR objects not xaml) in the code behind.

    Is there a way to build the UI in the viewmodel? Currently I have some not kosher (I think) connections where in the view I get a reference to the view model and subscribe to an event. That event is raised when the data needed to build the ui has been retrieved from the RIA service. I get the reference to the viewmodel in the view by casting the Datacontect to the viewmodel type.

    It works but is really ugly... I would love to see a cleaner viewmodel only example of how to do this. If it is possible.

    BOb
  5. pgsays:
    There is an alternative to the approach suggested 'To bind controls added using dynamically-loaded XAML... '
    and that is to simply include the binding expressions in your XAML and then assign your ViewModel to the DataContext using code behind. For example:
    UIElement tree = (UIElement)XamlReader.Load(xaml);
    LayoutRoot.Children.Add(tree);
    LayoutRoot.DataContext = _vm;
    or
    FrameworkElement tree = (FrameworkElement)XamlReader.Load(xaml);
    LayoutRoot.Children.Add(tree);
    tree.DataContext = _vm;
  6. David Espinosays:
    Sure is really interesting!!. Is it true?, xaml parsing is faster than CLR objects?. I personally preffer to use CLR objects, because you are working with strongly typed objects, you have a more understandable code and it's easy to mantain, you have Intellisence syntax support, and if you want to attach and event, you can do that at the same time you create the object, otherwise you have to do a FindControl and then attach the event. But I'm curious about performance issues, do you have any kind of information about the faster method?

    Regards
  7. Daniel Vogtsays:
    Hi Pete!

    Your article reminds me of the old method called createFromXaml() which we used extensively when we developed several RIA's in Silverlight 1 with JavaScript.
    This kind of building a dynamic control is much easier than finding out how to write it programmatically.
    But that leads to a feature that I was missing since Silverlight came up both in Visual Studio and in Expression Blend: There should be a possibility to translate a Xaml-String to CLR-code automatically (maybe for a marked Xaml-string in a Xaml-file when you click the right mouse button). Do you know whether there is anything in place or even still exists? This would be a very helpful feature...

    Daniel
  8. Paulussays:
    Hi Pete,

    A step further ...

    Would it also be possible to subsequently unload, reload that "dynamic control" without further ado, e.g. to optimize the visual tree performance, using [...].Children.Clear() then Children.Add()

    F.i. when Children have their own event handlers setup at "Load", should the Root explicitly ask the children to unhook those or will the "system" invoke those children for you via the "Unload" event?

    No memory leaks to expect from using such technique?

    Thanks, Paulus
  9. Eric Hychesays:
    Pete,

    I found this blog post when I posted a question on a Windows Phone 7 AppHub forum:

    http://forums.create.msdn.com/forums/p/69317/423237.aspx#423237

    and your approach of dynamically generating the XAML would work for me. However, is it possible to take it one step further, and completely generate an entire PhoneApplicationPage in XAML and then navigate to it using NavigationService.Navigate()?

    For instance, here's what I'd like to do (please refer to my original post):

    1) Using WebClient, retrieve an XML file containing the proprietary layout markup
    2) Use an XSLT transform to convert this proprietary markup to a XAML PhoneApplicationPage
    3) Store this generated XAML "somewhere" (perhaps isolated storage?)
    4) Then navigate to this dynamically generated XAML page via NavigationService.Navigate()

    Is this possible?

    Thanks!

    Eric
  10. Developersays:
    I wonder how this dynamic control generation can fit into a MVVM architecture where the data returned from a WCF call will contain the information necessary (for ex button.Width = 80; button.Height = 25; button.Content = "Save"; button.SetProperty(Canvas.LeftProperty, 50); button.SetProperty(Canvas.TopProperty, 50)) to display the controls on the UI.

    If the data returned from WCF calls passes through Model which INPC's the ViewModel, simply INPC'ing the View will not be of any use to generate the control dynamically.

    Also ViewModel should have no knowledge about the View, so which file should this runtime XAML generating code go into? Putting it into the code behind for View will break the MVVM architecture.

    Will a Controller be of help here? Like Model issuing a callback to a Controller which has knowledge about the View which can then run this XAML generating code? MVVM+C?

    ViewModel coexists to databind other parts of View which the runtime generation can be handled by Controller? Is this a good/only way?
  11. Ajosays:
    I have used your turorial to create a dynamic canvas with textblock.. when I try reloading that canvas after saving to xaml file How can I rebind the textblocks in it to the same event...
    Here I am using 3 events
    uiEle.MouseMove += new MouseEventHandler(Element_MouseMove);
    uiEle.MouseLeftButtonDown += new MouseButtonEventHandler(Element_MouseLeftButtonDown);
    uiEle.MouseLeftButtonUp += new MouseButtonEventHandler(Element_MouseLeftButtonUp);

    All are used to reposition my controls... uiEle is a TextBlock object
  12. Adrianasays:
    Hello!
    Thank you for a very interesting post! I am creating a mobile App dynamically and so far I am able to manage more or less all the controls, but I can't create Pages! I have tried to instantiate PhoneApplicationPage, and Page, but I can't access.. Should I create all the xaml files dynamically? I don't have a lot of experience, but It doesn't look very right... and looks very complicated!
    Please somebody help me!!!
    Thank you very muchhhhh :-)
  13. James says:
    'To bind controls added using dynamically-loaded XAML, you'll need to provide a valid Name to each control you want to reference, then use FindName after loading to get a reference to the control. From there, you can using the Binding object and SetBinding method.'

    I've tried this, but I'm new to Silverlight and I'm obviously doing something wrong. Can you please finish off the example with the code needed to Name, Find and Bind the TextBlock?
  14. Jimsays:
    UIElement tree = (UIElement)XamlReader.Load(xmlReader);
    when i tried to store the xaml design code as what you mentioned, somehow code above shows error "Data at the root level is invalid. Line 1, position 1." that shows error on the first line of my the string "string xaml = "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'" +......
    any idea what is wrong with the error?
  15. Petesays:
    @Jim

    Xaml needs to follow xml rules. Looks like you're missing the opening delcaration (the left angle bracket and the tag)

    @James

    I'll try and put something together for your after MIX11. Remind me in a couple weeks.

    Pete
  16. Jimsays:
    Hey pete,

    yet i still get this error "The '=' character, hexadecimal value 0x3D, cannot be included in a name. Line 1, position 7." from the same line of code. any idea?
  17. Jimsays:
    @Pete,

    I tried and it came to the last error
    'Cannot create unknown type '{clr-namespace:WPFDemo}CarouselControl'.' Line number '1' and line position '2'.
    from the code below:

    "<demoControls:CarouselControl x:Name='one' Width='60' Height='60' Canvas.Left='268.82' " +
    "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' " +
    "xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' " +
    "xmlns:demoControls='clr-namespace:WPFDemo'>" + ......

    it works fine in my design. but not at code behind. Any idea?
  18. Max Yaffesays:
    Pete, thanks for this post.
    Being new to WPF, I'm having trouble understanding the syntax:
    "xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' "
    and
    "<TextBox x:Name='FirstName' Margin='3' Grid.Row='0' Grid.Column='1' />"

    How is this translated into C#. I see the line

    var firstNameField = CreateTextBox(new Thickness(3), 0, 1);

    but don't grok how you translated from XAML to C# here.

    Is there any concise explanation of this syntax.
    Thanks


  19. Petesays:
    @Max

    Every element you see in XAML has a corresponding object in the runtime. So, the exact code to replicate the TextBox you created would be something like:

    TextBox FirstName = new TextBox();
    FirstName.Margin = new Thickness(3);
    FirstName.SetProperty(Grid.RowProperty, 0);
    FirstName.SetProperty(Grid.ColumnProperty, 1);

    I wrote that code in the text editor here, so may have the attached propert (grid.row/grid.column) syntax a bit off.

    The "CreateTextBox" method was a helper I wrote to encapsulate some of those property settings.

    The "xmlns:x" bit is XML syntax. Shameless plug: I explain that early in my Silverlight book (see the right margin for link)

    Hope that helps.

    Pete

  20. shashiksays:
    is this shows the same thing or different, if different what will be the more accurate? please help me..

    Run-time XAML code compiler:
    http://howsharepoint.blogspot.com/2011/11/run-time-xaml-code-compiler.html
  21. Robertsays:
    The creation of a control at runtime using the xaml string has the disadvantage of being inaccessible to Expression Blend. Is there any way to create the control at runtime using statically loaded XAML?
  22. Petesays:
    @Robert

    Embed it in your project as a resource file and then load it from a resource stream at runtime, like you would an embedded image or XML file.

    That said, if you're going through that trouble, just create it as a usercontrol; you're not really doing anything dynamic anyway.

    Pete
  23. Robertsays:
    @Pete

    Thanks for your prompt response. There are actually two dynamic aspects of this control (an Expander control) created at runtime:

    1) I need to customize the colors including the mouseover "Hover" colors which are hard coded (valid versus invalid), based on the whistlerblue.xaml file that we were using previously. Hence I have two xaml files containing control templates (that will denote either valid or invalid content) for the Expander control.

    2) I need to create an arbitrary number of these controls, the exact count not being known until runtime.

    Embedding these controls at as a resource file will apparently make them inaccessible to ExpressionBlend. I guess I'll just have to include these xaml files in the folder where the program is installed.

    Thanks,
    Robert
  24. Petesays:
    @Robert

    Perhaps I misunderstood your scenario, but wouldn't you include the control templates in two different resource dictionaries, and only merge in the one you plan to use?

    You could also use styles and make sure the template uses TemplateBinding to get the correct colors.

    Pete
  25. Robertsays:
    In retrospect I think the approach you mentioned with styles and TemplateBinding is the best choice. I had never done anything with TemplateBinding before because I am relatively new to XAML. Thanks again.

  26. Nassim Beirutysays:
    Hello Pete, i have an table called alfa(in sql)...
    how can i fill the data of this table in a datagrid using binding method ( WPF ).
    i dont want to use this one :
    dg.ItemsSource = e.Result;
    i want to design my datagrid as columns i dont want to show all the columns in the table , and i need to add a column...
    so is there any suggestion that can help me ...
    waiting Your Reply .
    Thank You In Advance
    Nassim Beiruty
  27. Bilqiissays:
    Hello Pete,
    Great article! Please I ran into a problem while trying to bind other controls to the initialized data. I used the following cade for the lastname as follows:
    Binding lastNameBinding = new Binding();
    lastNameBinding.Source = _ln;
    lastNameBinding.Path = new PropertyPath("LastName");
    lastNameBinding.Mode = BindingMode.TwoWay;
    lastNameBinding.SetBinding(TextBox.TextProperty, lastNameBinding);
    But the SetBinding is throwing error, that a reference is missing but works only for firstname control. Please advice. Thanks in advance
  28. Bilqiissays:
    Thanks for the quick response. Actually the new instance of the System.Windows.Data.Binding class is "lastNameBinding" and not "lastNameTextBox" just as your naming style in the demo. The SetBinding only works with the firstname variable created firts. Is it that I can't create multiple instance of the Binding class within a single method? I hope you can help me better now.
  29. Bilqiissays:
    Your example also did not display the initialised values upon loading both in wpf(when the save button is clicked) and silverlight. Its only the firname value "Pete" that is displayed and I suspected it was because the binding wasn't implemented for both the lastname and the datetimepicker controls during creation.
  30. Bilqiissays:
    Ok, this is the error displayed:
    Error 1 'System.Windows.Data.Binding' does not contain a definition for 'SetBinding' and no extension method 'SetBinding' accepting a first argument of type 'System.Windows.Data.Binding' could be found (are you missing a using directive or an assembly reference?)
    while this is the code:
    var lastNameField = CreateTextBox(new Thickness(3), 1, 1);

    Binding lastNameBinding = new Binding();
    lastNameBinding.Source = _ln;
    lastNameBinding.Path = new PropertyPath("LastName");
    lastNameBinding.Mode = BindingMode.TwoWay;
    lastNameBinding.SetBinding(TextBox.TextProperty, lastNameBinding);

    rootGrid.Children.Add(lastNameField);
    Thanks for your patience and understanding. I am a beginner
  31. Dalpatsays:
    Sir,
    1.Creating Controls at runtime using Code and CLR Objects
    2.Creating Controls at Design Time in XAML
    3.Creating Controls at runtime using XAML strings
    which way is best for better performance and speed?
  32. Petesays:
    @Dalpat

    Creating instances of existing controls using Code and CLR objects, in Windows 8, should provide marginally better performance, but only marginally.

    If, however, you completely did away with all markup and created a control from scratch, with elements created from code not a control template, so no XAML parsing was involved, it would be faster.

    But even then, it really only makes a difference when you're creating a ton of them. For example: in the data template of a GridView.

    I'd encourage you to do your own performance testing using Xperf and other tools. See the XAML performance talk from Build 2012, and also my talk from TechEd India 2013 (video should be up in a week or so).

    Pete
  33. Viveksays:
    Thanks Pete,
    This is exactly what I was looking from many days. I have used XSLT transformation in ASP.NET to generate UI dynamically, now I want to do same thing in WPF. In short my application is similar to objective exam paper where application dynamically renders different types of question like select choice, multiple choice, select date and some more complex type like disable next 2 question if answer of first question skip next 2 question etc.

    Since I cannot hard code questions and answers at the design time, what option (CLR object, XMAL) will work for me to generate ? Also Is it feasible to use MVVM design framework for this application, I am not sure such fine flexibility can be achieved from MVVM and commands.

    Thanks, looking forward for your response.
  34. Amitsays:
    Hi Pete,
    var firstNameField = (TextBox)FindName("FirstNameField"); gives me a null value.

    I have added the controls via string into Xaml as an UIElement and given name to each textbox control,
    I am able to achieve binding, but a FIndName gives me a null value. I am even able to provide duplicate names to controls with no compiling issue.
    Please help.


  35. Kirstin Walshsays:
    I have a data entry form in WPF in which the same line(s) are added as many times as the user wants on a button click event. Can I use the same method you describe to bind data from these textboxes since they won't have unique names?
    I tried to do this in a datagrid, but am getting too many bugs that I can't work out (fairly new programmer and even newer to WPF). github.com/pyxis828/tournymanager

Comment on this Post

Remember me