Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8178549
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T23:47:37+00:00 2026-06-06T23:47:37+00:00

In my MVVM WPF application I’m using a databound flowdocument. I used the technique

  • 0

In my MVVM WPF application I’m using a databound flowdocument. I used the technique described here to be able bind my data to the flowdocument.
My flowdocument is bound to a public property in my viewmodel. The property is an ienumerable of a custom type, like this:

public IEnumerable<Person> Persons
{
    get { return _persons; }
    set { _persons = value; }
}

The flowdocument is shown in a FlowDocumentScrollViewer control. The document looks like:

code    name    lastname
----    -----   ---------
1       john    johnson
1       peter   peterson
2       jane    jane
3       john    doe

The binding works fine however I want to add a blank line after each distinct code:

code    name    lastname
----    -----   ---------
1       john    johnson
1       peter   peterson

2       jane    jane

3       john    doe

My Xaml in the view is:

<FlowDocumentScrollViewer>
  <FlowDocument>
    <flowdoc:ItemsContent ItemsSource="{Binding Path=Persons}">
      <flowdoc:ItemsContent.ItemsPanel>
        <DataTemplate>
          <flowdoc:Fragment>
            <Table BorderThickness="1" BorderBrush="Black">
              <TableRowGroup flowdoc:Attached.IsItemsHost="True">
                <TableRow Background="LightBlue">
                  <TableCell>
                   <Paragraph>ronde</Paragraph>
              </TableCell>
              <TableCell>
                <Paragraph>hal</Paragraph>
              </TableCell>
              <TableCell>
                <Paragraph>datum</Paragraph>
              </TableCell>
            </TableRow>
          </TableRowGroup>
        </Table>
      </flowdoc:Fragment>
    </DataTemplate>
  </flowdoc:ItemsContent.ItemsPanel>
  <flowdoc:ItemsContent.ItemTemplate>
    <DataTemplate>
      <flowdoc:Fragment>
        <TableRow>
          <TableCell>
            <Paragraph>
              <flowdoc:BindableRun BoundText="{Binding Path=Code}" />
            </Paragraph>
          </TableCell>
          <TableCell>
            <Paragraph>
              <flowdoc:BindableRun BoundText="{Binding Path=Name}" />
            </Paragraph>
          </TableCell>
          <TableCell>
            <Paragraph>
              <flowdoc:BindableRun BoundText="{Binding Path=LastName}" />
            </Paragraph>
          </TableCell>
        </TableRow>
      </flowdoc:Fragment>
    </DataTemplate>
  </flowdoc:ItemsContent.ItemTemplate>
</flowdoc:ItemsContent>

Any suggestions on how to do this without breaking the MVVM rules? It seems like databinding a flowdocument comes with the price of inflexible layout.

Thanks in advance

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T23:47:38+00:00Added an answer on June 6, 2026 at 11:47 pm

    In order to group your data, use a CollectionViewSource like this:

    <Window.Resources>
        <CollectionViewSource x:Key="groupView" Source="{Binding Path=Persons}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="Code"/>
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </Window.Resources>
    <Grid>
        <FlowDocumentScrollViewer>
            <FlowDocument>
                <flowdoc:ItemsContent ItemsSource="{Binding Source={StaticResource groupView}}">
                   ....
                </flowdoc:ItemsContent>
            </FlowDocument>
        </FlowDocumentScrollViewer>
    </Grid>
    

    The CollectionViewSource element above sorts the Persons list by code and determines the groups.

    Furthermore, you must adapt the ItemsContent class, because the one from the MSDN article does not yet support grouping. Here is a very simple example how you could achieve that:

    private void GenerateContent(DataTemplate itemsPanel, DataTemplate itemTemplate, IEnumerable itemsSource)
    {
        Blocks.Clear();
        if (itemTemplate != null && itemsSource != null)
        {
            FrameworkContentElement panel = null;
    
            if (panel == null)
            {
                if (itemsPanel == null)
                {
                    panel = this;
                }
                else
                {
                    FrameworkContentElement p = Helpers.LoadDataTemplate(itemsPanel);
                    if (!(p is Block))
                    {
                        throw new Exception("ItemsPanel must be a block element");
                    }
                    Blocks.Add((Block)p);
                    panel = Attached.GetItemsHost(p);
                    if (panel == null)
                    {
                        throw new Exception("ItemsHost not found. Did you forget to specify Attached.IsItemsHost?");
                    }
                }
            }
    
            // *** START NEW CODE ***
            ICollectionView view = itemsSource as ICollectionView;
            if (view != null)
            {
                foreach (object group in view.Groups)
                {
                    GenerateContentForUngroupedItems(itemsPanel, itemTemplate, ((CollectionViewGroup)group).Items, panel);
                    if (panel is TableRowGroup)
                    {
                        TableRow row = new TableRow();
                        row.Cells.Add(new TableCell());
                        ((TableRowGroup)panel).Rows.Add(row);
                    }
                }
            }
            else
            {
                GenerateContentForUngroupedItems(itemsPanel, itemTemplate, itemsSource, panel);
            }
            // *** END NEW CODE ***
        }
    }
    
    private void GenerateContentForUngroupedItems(DataTemplate itemsPanel, DataTemplate itemTemplate,
                                                    IEnumerable itemsSource, FrameworkContentElement panel)
    {
        foreach (object data in itemsSource)
        {
            FrameworkContentElement element = Helpers.LoadDataTemplate(itemTemplate);
            element.DataContext = data;
            Helpers.UnFixupDataContext(element);
            if (panel is Section)
            {
                ((Section) panel).Blocks.Add(Helpers.ConvertToBlock(data, element));
            }
            else if (panel is TableRowGroup)
            {
                ((TableRowGroup) panel).Rows.Add((TableRow) element);
            }
            else
            {
                throw new Exception(String.Format("Don't know how to add an instance of {0} to an instance of {1}",
                    element.GetType(), panel.GetType()));
            }
        }
    }
    

    Most of the code above is from the original MSDN article; the only changes I made are these:

    • Moved the foreach loop to the new method GenerateContentForUngroupedItems.
    • Moved the panel creation code (“if (panel==null)“) outside the loop.
    • Added the code marked NEW CODE.

    What the modified code does is this: if the items source is not a collection view, it works exactly like the original MSDN code. If the items source is a collection view, two nested loops are called:

    • The outer loop iterates over all groups.
    • The inner loop iterates over all items in the current group.

    The inner loop effectively is the same as the original foreach loop from the MSDN article.

    In the added code above, the empty table row is added by these lines:

    TableRow row = new TableRow();
    row.Cells.Add(new TableCell());
    ((TableRowGroup)panel).Rows.Add(row);
    

    This code, of course, is not very generic. For a generic solution, add a new dependency property to the ItemsContent control which contains a data template, just like the ItemsPanel or ItemTemplate properties. Then, you have the possibility to insert arbitrary text at the end of the group.

    The result looks like this:

    Grouped flow document

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am developing a WPF application using the MVVM pattern as described by Josh
I am developing an application using WPF/MVVM. I have a WCF data service project
My WPF application is structured using the MVVM pattern. The ViewModels will communicate asynchronously
In my WPF application using MVVM I noticed that in some cases the CanExecute
I am using MVVM Light toolkit in my WPF application. I would like to
I have a WPF application using MVVM. I have some user controls that show
I have a WPF application implemented using the MVVM framework that uses an ActiveX
I have a wpf application using mvvm approach. The main window contains a tab
I'm working on an WPF application using the mvvm-light framework. I'm new to both
I'm writting an WPF application using the mvvm toolkint. In the main windows I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.