Tips Tricks and Techniques for Building Killer Silverlight
Tips, Tricks, and Techniques for Building Killer Silverlight Apps Jeff Prosise http: //www. wintellect. com/CS/blogs/jprosise/default. aspx http: //twitter. com/#!/jprosise
Dynamic Assembly Loading • Assembly. Part class represents an assembly that's part of a Silverlight application • Assemblies typically packaged in XAPs • Assembly. Part. Load loads assemblies into appdomains at runtime • The key to dynamic assembly loading, but… • Beware the JIT compiler! 2
Loading an Assembly Web. Client wc = new Web. Client(); wc. Open. Read. Completed += On. Open. Read. Completed; wc. Open. Read. Async(new Uri("Widget. dll", Uri. Kind. Relative)); . . . private void On. Open. Read. Completed(object sender, Open. Read. Completed. Event. Args e) { if (e. Error == null) { Assembly. Part part = new Assembly. Part(); part. Load(e. Result); } } 3
DEMO Dynamic Assembly Loading
Dynamic XAP Loading • XAPs can be loaded dynamically, too • Download with Web. Client • Extract App. Manifest. xaml from XAP and enumerate assemblies ("parts") • Extract assemblies and load with Assembly. Part. Load • Create class-library XAP by starting with Silverlight Application, not Silverlight Class Library
Enumerating Assemblies in a XAP Stream. Resource. Info sri = new Stream. Resource. Info(xap, null); Xml. Reader reader = Xml. Reader. Create (Application. Get. Resource. Stream(sri, new Uri("App. Manifest. xaml", Uri. Kind. Relative)). Stream); Assembly. Part. Collection parts = new Assembly. Part. Collection(); if (reader. Read()) { reader. Read. Start. Element(); if (reader. Read. To. Next. Sibling("Deployment. Parts")) { while (reader. Read. To. Following("Assembly. Part")) { parts. Add(new Assembly. Part() { Source = reader. Get. Attribute("Source") }); } } } 6
Loading Enumerated Assemblies foreach (Assembly. Part part in parts) { Stream assembly = Application. Get. Resource. Stream (sri, new Uri(part. Source, Uri. Kind. Relative)). Stream; part. Load(assembly); } 7
DEMO Dynamic XAP Loading
Dynamic Localization • Silverlight supports RESX localization • Create resource DLLs from RESX files • Resource DLLs == Satellite assemblies • Data-bind XAML elements to auto-generated Resource. Manager wrapper • Two challenges • How do you switch languages at run-time? • How do you download satellite assemblies on demand rather than embed them in the XAP?
Observable. Resources public class Observable. Resources<T> : INotify. Property. Changed { public event Property. Changed. Event. Handler Property. Changed; private static T _resources; public T Localization. Resources { get { return _resources; } } public Observable. Resources(T resources) { _resources = resources; } public void Update. Bindings() { if (Property. Changed != null) Property. Changed(this, new Property. Changed. Event. Args("Localization. Resources")); } } 10
Enumerating Satellite Assemblies Stream. Resource. Info sri = new Stream. Resource. Info(xap, null); Xml. Reader reader = Xml. Reader. Create (Application. Get. Resource. Stream(sri, new Uri("App. Manifest. xaml", Uri. Kind. Relative)). Stream); Assembly. Part. Collection parts = new Assembly. Part. Collection(); if (reader. Read()) { reader. Read. Start. Element(); if (reader. Read. To. Next. Sibling("Deployment. Parts")) { while (reader. Read. To. Following("Assembly. Part")) { parts. Add(new Assembly. Part() { Source = reader. Get. Attribute("Source") }); } } } 11
Loading Satellite Assemblies foreach (Assembly. Part part in parts) { if (part. Source. To. Lower(). Contains("resources. dll")) { Stream assembly = Application. Get. Resource. Stream (sri, new Uri(part. Source, Uri. Kind. Relative)). Stream; part. Load(assembly); } } 12
DEMO Dynamic Localization
Dynamic Page Loading • Navigation framework provides infrastructure for multi-page apps • Default content loader loads pages from XAP • Page. Resource. Content. Loader • No built-in support for remote XAPs • Custom content loaders can load them from anywhere • -INavigation. Content. Loader
Do-Nothing Content Loader public class Custom. Content. Loader : INavigation. Content. Loader { private Page. Resource. Content. Loader _loader = new Page. Resource. Content. Loader(); public IAsync. Result Begin. Load(Uri target. Uri, Uri current. Uri, Async. Callback user. Callback, object async. State) { return _loader. Begin. Load(target. Uri, current. Uri, user. Callback, async. State); } public bool Can. Load(Uri target. Uri, Uri current. Uri) { return _loader. Can. Load(Add. File. Name. Extension(target. Uri), current. Uri); } public void Cancel. Load(IAsync. Result async. Result) { _loader. Cancel. Load(async. Result); } public Load. Result End. Load(IAsync. Result async. Result) { return _loader. End. Load(async. Result); } } 15
Registering a Content Loader <nav: Frame x: Name="Main" Source="Home"> <nav: Frame. Content. Loader> <local: Custom. Content. Loader /> </nav: Frame. Content. Loader> </nav: Frame> 16
DEMO Dynamic Page Loading
Behaviors • Combine triggers and actions into one package • Useful when user-input events and actions taken in response to those events are tightly bound • e. g. , drag behavior requires coupling of Mouse. Left. Button. Down, Mouse. Move, and Mouse. Left. Button. Up events • Derive from Behavior or Behavior<T> • Override On. Attached and On. Detaching • Associated. Object property references attachee 18
Implementing a Behavior public class Disappear. Behavior : Behavior<UIElement> { protected override void On. Attached() { base. On. Attached(); Associated. Object. Mouse. Left. Button. Down += On. Click; } protected override void On. Detaching() { base. On. Detaching(); Associated. Object. Mouse. Left. Button. Down -= On. Click; } private void On. Click(object sender, Mouse. Button. Event. Args e) { Associated. Object. Visibility = Visibility. Collapsed; } } 19
Applying a Behavior xmlns: local="clr-namespace: namespace" xmlns: i="clr-namespace: System. Windows. Interactivity; assembly=System. Windows. Interactivity". . . <Rectangle Width="300" Height="200" Fill="Red"> <i: Interaction. Behaviors> <local: Disappear. Behavior /> </i: Interaction. Behaviors> </Rectangle> 20
DEMO Behaviors
Stay up to date with MSDN Belux • Register for our newsletters and stay up to date: http: //www. msdn-newsletters. be • Technical updates • Event announcements and registration • Top downloads • Follow our blog Download http: //blogs. msdn. com/belux MSDN/Tech. Net Desktop Gadget http: //bit. ly/msdntngadget • Join us on Facebook http: //www. facebook. com/msdnbelux • Linked. In: http: //linkd. in/msdnbelux/ • Twitter: @msdnbelux
Tech. Days 2011 On-Demand • Watch this session on-demand via Channel 9 http: //channel 9. msdn. com/belux • Download to your favorite MP 3 or video player • Get access to slides and recommended resources by the speakers
THANK YOU
- Slides: 24