Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF: Simple Bridge between a FrameworkElement and a FramworkContentElement

0.00/5 (No votes)
29 Dec 2009 2  
Q: Have you ever tried to embed a FramworkContentElement into a FrameworkElement inside a WPF template?Consider the following: This won't work! ...
Q: Have you ever tried to embed a FramworkContentElement into a FrameworkElement inside a WPF template?

Consider the following:

<DataTemplate>
  <TableRow>
   <TableCell>
     <Paragraph>
       <FlowDocumnet>
         <Paragraph>
           This won't work!
         </Paragraph>
       </FlowDocument>
     </Paragraph>
   </TableCell>
  </TableRow>
</DataTemplate>


I found this problem and solution in the April 2009 ed. of MSDN. The article is about 'Dynamic WPF' How to data bind in flow documents. The problem and solution in the article is how do you create a data bound list item which can be copied and pasted using the windows clipboard in a document? The solution to that goes beyond the topic of this tip and can be found at: Code for "Create Flexible UIs with Flow Documents And Data Binding"[^]. However I thought section on creating a 'bridge' between FrameworkElements and FrameworkContentElements was a good candidate for a short tip/trick on WPF.

You may ask your self why build a bridge when there are already bridges hosted in the .NET WPF framework such as: BlockUIContainer and TextBlock? Well if you need to do more then simple 'in lines' you will need something different other then what the frame work has to offer.

Here is the solution as it appears in MSDN for creating a bridge:

Figure 1 - Fragment Class


[ContentProperty("Content")]
public class Fragment : FrameWorkElement
{
  private static readonly DependancyProperty ContentProperty =
  DependanceProperty.Register("Content", 
                              typeof(FrameworkContentElement),
                              typeof(Fragment));

  public FrameworkContnetElement Content
  {
    get
    {
      return (FrameworkContentElement)GetValue(ContentProperty);
    }
    set
    {
      SetValue(ContentProperty, value);
    }
  }
}


Now the folloing is possible:

<DataTemplate>
  <flowdoc:Fragment>
    <TableRow>...</TableRow>
  </flowdoc:Fragment>
</DataTemplate>


Figure 1 is the bridge which is really just a wrapper for the FrameworkContnetElement. However a helper method is required when displaying the data in the content element. The helper really where the trick is implemented. There is a problem encountered when re displaying the data in the Framework Element. The problem is that when displaying the data an enumerator is created and this causes an exception to be thrown. "Collection Modified..."

Here is the workaround in the help class:

Figure 2 - Helper Method



public static FrameworkContentElement LoadDataTemplate(
                                      DataTemplate dataTemplate)
{
  object content = dataTemplate.LoadContent();
  if(content is Fragment)
    return(FrameworkContentElement)((Fragment)content).Content;
  else if(content id TextBlock)
  {
   InlineCollection inlines = ((TextBlock)content).Inlines;
   if(inlines.Count == 1
     return inlines.FirstInline;
   else
   {
     Paragraph paragraph = new Parageraph();
     while(inlines.FirstInline != null)
      paragraph.Inlines.Add(inlines.FirstInline);
     return paragraph;
   }
  }
  else
   throw new Exception("Data Template needs to contain a <Fragment> or <TextBlock>");
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here