Dr. Dobb's Journal - August 2008 - (Page 38) Core Technology EMBED CUSTOM GUIS IN WPF continued from page 36 Serialization/Deserialization Go to the WPF Compound Documents sample app. Select Edit/Insert PhotoControl. Click on the PhotoControl’s Add button and add some JPEG files. Look at the XAML markup in the RichTextBox on the right. action, run the WPF Compound Documents app (Figure 2). The WPF Compound Documents app can deserialize, copy/paste, and print UserControls. Here’s how it works. Listing One // Convert UserControls into PlaceholderControls in the xaml markup. public static string ReplaceControlsWithPlaceholders(string xaml, TextPointer start, TextPointer end) { string modifiedMarkup = xaml; // Get a list of UserControl Name attribute values in the // order in which they appear in the document. List userControlNames = GetUserControlNames(start, end); // Search for each Name foreach (string name in userControlNames) { foreach (string typeName in ControlTypeNames) { string enhancedUserControl = string.Format(@"<{0} .*?Name=""{1}"".*? ", typeName, name); string placeHolderControl = string.Format(@" ", Regex enhancedUserControlRegex = new Regex(enhancedUserControl); // Replace the UserControl with a Placeholder control having // the same Name as the UserControl. modifiedMarkup = enhancedUserControlRegex.Replace( modifiedMarkup, placeHolderControl); } } return modifiedMarkup; } // Convert all PlaceholderControls in the document with // the UserControls that they represent. public static void ReplacePlaceholdersWithRealControls( FlowDocument document, RichTextBox richTextBox) { int replacements = 0; TextPointer current = document.ContentStart; // Scan through the entire document while (current.CompareTo(document.ContentEnd) < 0) { // UserControls will be nested in BlockUIContainer // or InlineUIContainer XAML elements. BlockUIContainer blockUIContainer = current.Parent as InlineUIContainer inlineUIContainer = current.Parent as // If we found a BlockUIContainer or InlineUIContainer if (blockUIContainer != null || inlineUIContainer != null) { PlaceholderControl placeHolderControl; if (blockUIContainer != null) { placeHolderControl = blockUIContainer.Child as PlaceholderControl; } else { placeHolderControl = inlineUIContainer.Child as } // If we found a PlaceholderControl if (placeHolderControl != null) { // Determine the type of the UserControl that the // PlaceholderControl represents. Type controlType = EnhancedUserControlUtils.GetType(placeHolderControl.Name); // Create a new UserControl of the proper type. IEnhancedUserControl newControl = EnhancedUserControlUtils.ControlFactory(controlType); // Change the name of the new control so that it won't // overwrite another control's data. newControl.Name = EnhancedUserControlUtils.NameFromGuid(Guid.NewGuid()); // Retrieve the UserControl's state data. ICloneable dataToPersist = (ICloneable)EnhancedUserControlUtils. Load(placeHolderControl.Name); // Clone the state data so that the new UserControl // won't overwrite another UserControl's data. ICloneable newObject = (ICloneable)dataToPersist.Clone(); // Save the new UserControl's type and state. Globals.CompoundDocument.PersitedTypes[newControl.Name] = Globals.CompoundDocument.PersitedValues[newControl.Name] = // Load the new UserControl with its state data. ((IEnhancedUserControl)newControl).Load(newObject); // Nest the new UserControl inside the BlockUIContainer // or InlineUIContainer. if (blockUIContainer != null) { blockUIContainer.Child = (UserControl)newControl; } else if (inlineUIContainer != null) { inlineUIContainer.Child = (UserControl)newControl; } replacements++; } } current=current.GetNextContextPosition(LogicalDirection.Forward); } } You’ll see that several of the PhotoControl’s XAML elements have Name attributes. But you can save and open the document by selecting File/Save and File|Open without encountering the dreaded XamlParseException. How? This sample application uses PlaceholderControls, which are minimalist UserControls with no content. PlaceholderControls have the same Name attribute value as the UserControls that they represent. The program avoids the deserialization issue by simply replacing all UserControls with PlaceholderControls before serializing the document, and replacing all PlaceholderControls with UserControls after deserializing. Converting between UserControls and PlaceholderControls is done by the ReplaceControlsWithPlaceholders and ReplacePlaceholdersWithRealControls methods (Listing One). ReplaceControlsWithPlaceholders first calls GetUserControlNames, which scans the specified document fragment and retrieves a list of UserControl Name attribute values in the order in which the UserControls appear in the fragment. Then it uses a regular expression to replace the UserControl markup with PlaceholderControl markup. ReplacePlaceholdersWithRealControls scans through the entire document looking for BlockUIContainers and InlineUIContainers because those elements contain each of the document’s PlaceholderControls. If it finds a BlockUIContainer or InlineUIContainer that contains a PlaceholderControl, it extracts the PlaceholderControl. Then it determines the type of UserControl represented by the PlaceholderControl. Finally, it creates the UserControl and loads it with state data so that it displays properly. Figure 2: Workarounds in action. 38 Dr. Dobb’s Journal l www.ddj.com l August 2008 http://www.ddj.com
Table of Contents Feed for the Digital Edition of Dr. Dobb's Journal - August 2008 Dr. Dobb's Journal - August 2008 Contents Friday Night Fish Fry Alia Vox Developer Diaries Developer’s Notebook A Conversation with Christos Papadimitriou OpenGL and Mobile Devices: Round 2 Ellipse Specification Using Vectors Embed Custom GUIs in WPF Building RIAs on J2EE Foundations Disentangling Concepts in Object-Oriented Systems The Agile Edge Effective Concurrency Swaine’s Flames Dr. Dobb's Journal - August 2008 Dr. Dobb's Journal - August 2008 - Dr. Dobb's Journal - August 2008 (Page Cover1) Dr. Dobb's Journal - August 2008 - Dr. Dobb's Journal - August 2008 (Page Cover2) Dr. Dobb's Journal - August 2008 - Dr. Dobb's Journal - August 2008 (Page 1) Dr. Dobb's Journal - August 2008 - Dr. Dobb's Journal - August 2008 (Page 2) Dr. Dobb's Journal - August 2008 - Dr. Dobb's Journal - August 2008 (Page 3) Dr. Dobb's Journal - August 2008 - Contents (Page 4) Dr. Dobb's Journal - August 2008 - Contents (Page 5) Dr. Dobb's Journal - August 2008 - Friday Night Fish Fry (Page 6) Dr. Dobb's Journal - August 2008 - Friday Night Fish Fry (Page 7) Dr. Dobb's Journal - August 2008 - Friday Night Fish Fry (Page 8) Dr. Dobb's Journal - August 2008 - Friday Night Fish Fry (Page 9) Dr. Dobb's Journal - August 2008 - Alia Vox (Page 10) Dr. Dobb's Journal - August 2008 - Alia Vox (Page 11) Dr. Dobb's Journal - August 2008 - Developer Diaries (Page 12) Dr. Dobb's Journal - August 2008 - Developer Diaries (Page 13) Dr. Dobb's Journal - August 2008 - Developer’s Notebook (Page 14) Dr. Dobb's Journal - August 2008 - Developer’s Notebook (Page 15) Dr. Dobb's Journal - August 2008 - A Conversation with Christos Papadimitriou (Page 16) Dr. Dobb's Journal - August 2008 - A Conversation with Christos Papadimitriou (Page 17) Dr. Dobb's Journal - August 2008 - A Conversation with Christos Papadimitriou (Page 18) Dr. Dobb's Journal - August 2008 - A Conversation with Christos Papadimitriou (Page 19) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 20) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 21) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 22) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 23) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 24) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 25) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 26) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 27) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 28) Dr. Dobb's Journal - August 2008 - OpenGL and Mobile Devices: Round 2 (Page 29) Dr. Dobb's Journal - August 2008 - Ellipse Specification Using Vectors (Page 30) Dr. Dobb's Journal - August 2008 - Ellipse Specification Using Vectors (Page 31) Dr. Dobb's Journal - August 2008 - Ellipse Specification Using Vectors (Page 32) Dr. Dobb's Journal - August 2008 - Ellipse Specification Using Vectors (Page 33) Dr. Dobb's Journal - August 2008 - Ellipse Specification Using Vectors (Page 34) Dr. Dobb's Journal - August 2008 - Ellipse Specification Using Vectors (Page 35) Dr. Dobb's Journal - August 2008 - Embed Custom GUIs in WPF (Page 36) Dr. Dobb's Journal - August 2008 - Embed Custom GUIs in WPF (Page 37) Dr. Dobb's Journal - August 2008 - Embed Custom GUIs in WPF (Page 38) Dr. Dobb's Journal - August 2008 - Embed Custom GUIs in WPF (Page 39) Dr. Dobb's Journal - August 2008 - Building RIAs on J2EE Foundations (Page 40) Dr. Dobb's Journal - August 2008 - Building RIAs on J2EE Foundations (Page 41) Dr. Dobb's Journal - August 2008 - Building RIAs on J2EE Foundations (Page 42) Dr. Dobb's Journal - August 2008 - Building RIAs on J2EE Foundations (Page 43) Dr. Dobb's Journal - August 2008 - Building RIAs on J2EE Foundations (Page 44) Dr. Dobb's Journal - August 2008 - Building RIAs on J2EE Foundations (Page 45) Dr. Dobb's Journal - August 2008 - Disentangling Concepts in Object-Oriented Systems (Page 46) Dr. Dobb's Journal - August 2008 - Disentangling Concepts in Object-Oriented Systems (Page 47) Dr. Dobb's Journal - August 2008 - Disentangling Concepts in Object-Oriented Systems (Page 48) Dr. Dobb's Journal - August 2008 - Disentangling Concepts in Object-Oriented Systems (Page 49) Dr. Dobb's Journal - August 2008 - The Agile Edge (Page 50) Dr. Dobb's Journal - August 2008 - The Agile Edge (Page 51) Dr. Dobb's Journal - August 2008 - The Agile Edge (Page 52) Dr. Dobb's Journal - August 2008 - Effective Concurrency (Page 53) Dr. Dobb's Journal - August 2008 - Effective Concurrency (Page 54) Dr. Dobb's Journal - August 2008 - Effective Concurrency (Page 55) Dr. Dobb's Journal - August 2008 - Swaine’s Flames (Page 56) Dr. Dobb's Journal - August 2008 - Swaine’s Flames (Page Cover3) Dr. Dobb's Journal - August 2008 - Swaine’s Flames (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.