I received a customer request for how a XAML downloaded from a server can still have events. Let’s discuss the options for .NET 3.x, 4 and Silverlight.
Option 1: Compile your XAML (works in v3, v4, and Silverlight)
By default, when you add a XAML page into a project in VS or Blend, its BuildAction (shown in the properties pane – F4) is Page. When you build the assembly, MarkupCompilePass1 and MarkupCompilePass2 will analyze all the Pages and generate generated code files (.g.cs, .g.vb, etc…) and .baml files. When you navigate to the url of the XAML or do a new of the class defined in the XAML, it will end up calling Application.LoadComponent, which will load the class and the baml file. Every element in XAML that has a name or an event handler declared will end up calling IComponentConnector.Connect() in the generated code file, where we will wire the field that matches any name on that element, and wires any events. I can go deeper in this space if necessary, but you could also read this old post: “XAML, BAML, .g.cs details”
For Silverlight, there is no BAML, but we still create a generated code file and wire named objects to fields. Event wire up is handled by the parser.
Option 2: Don’t send UI from server, send data (works in v3, v4, and Silverlight)
Often people are used to sending HTML + Script from the server to the client. Since WPF (and Silverlight) has great databinding capabilities, you should rethink what you actually need to send down to the client for this kind of scenario. Often it is the data that changes often, and the UI is more static. You could Databind to downloaded XML data in an XmlDataProvider object.
Option 3a: Use XamlReader.Load() (no compiling) and specify event handlers in XAML (works in v4 and Silverlight)
In .NET 4, we have replaced the XAML plumbing for WPF. One of the new capabilities is that XamlReader.Load can handle event attributes declared in XAML. V3 used to throw a parse exceptions.
<Button Click="handle_ok">Ok</Button>
V4 will look for an method on the root object of the XAML file called handle_ok. So, if you know the set of methods you’ll have, you could send down a XAML with the appropriate root object and specify events as attributes in the XAML.
Option 3b: Use XamlReader.Load() (no compiling) and specify event handlers with a MarkupExtension (works in v4)
If having the methods located on the Root object doesn’t work for your scenario, v4 allows you to provide any markupextension that will return a Delegate as the value for an event in XAML.
<Button Click="{Run MyRoutine,Ok}">Ok</Button
You could build the RunExtension class so that it finds MyRoutine anywhere you want. You can also pass along parameters to that event, as you please.
Option 3c: Use XamlReader.Load() (no compiling) and specify event handlers with a DLR language via a markup extension (works in V4)
One could build a markupextension that can run code, perhaps with the DLR.
<Button Click="{RunCode 'textBox1.Text = lastName.Text + ", " + firstName.Text;'}">ok</Button>
The RunCodeExtension would need to know how to call into the DLR, and it would also need to use IXamlNameResolver to have access to the set of named objects that might be refered to in code.
Option 4: Integrate the DLR via a markup extension (works in v3 and v4)
In 2008, Daniel Paul wrote a 6 part series that explores adding DLR code into XAML. Part 5 explores writing Event handlers.
Option 5: Use XamlReader.Load, and wire events with FindName afterwards (works in v3)
See style #2 in “3 Coding Styles for Avalon Applications”