2012-07-04 82 views
2

在我的MVVM WPF應用程序中,我使用了一個數據綁定flowdocument。我使用描述的技術here能夠將我的數據綁定到flowdocument。 我的flowdocument綁定到我的viewmodel中的公共屬性。屬性是一個IEnumerable自定義類型的,例如:在數據綁定中插入分隔符(空白行)flowdocument

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

所述的FlowDocument以FlowDocumentScrollViewer控制所示。該文件看起來像:

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

精細的綁定工作,但是我想每個不同的代碼後添加一個空行:

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

2  jane jane 

3  john doe 

我的XAML中的觀點是:

<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> 

有關如何在不破壞MVVM規則的情況下做到這一點的任何建議?數據綁定流程文檔似乎與不靈活佈局的價格相關。

在此先感謝

+0

我想你提到的應該是[創建靈活的用戶界面隨着流量的文件和數據綁定]鏈接(http://msdn.microsoft.com/en-我們/雜誌/ dd569761.aspx)。 – 2012-07-05 07:02:27

+0

是的,你說得對。這是正確的聯繫。我剛剛糾正了上面的鏈接。謝謝! – svr

回答

3

爲了組數據,使用一個CollectionViewSource這樣的:

<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> 

CollectionViewSource上述各種元素的Persons列表由代碼,並且確定組。

此外,您必須修改ItemsContent類,因爲MSDN文章中的一個還不支持分組。這裏是一個非常簡單的例子,你如何能做到這一點:

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())); 
     } 
    } 
} 

大部分的代碼以上是從原來的MSDN文章;只有我所做的更改是這些:

  • 移動foreach環新方法GenerateContentForUngroupedItems
  • 將循環外部的面板創建代碼(「if (panel==null)」)移出。
  • 添加了標記爲NEW CODE的代碼。

修改後的代碼所做的事情是:如果items源不是集合視圖,它的工作方式與原始MSDN代碼完全相同。如果項源是一個集合視圖,則調用兩個嵌套循環:

  • 外層循環遍歷所有組。
  • 內部循環遍歷當前組中的所有項目。

內循環與MSDN文章中的原始foreach循環有效相同。

在上述添加的代碼,空表格行由這些線加入:

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

此代碼,當然,不是非常通用的。對於通用解決方案,將新的依賴項屬性添加到包含數據模板的ItemsContent控件中,就像ItemsPanelItemTemplate屬性一樣。然後,您可以在該組的最後插入任意文本。

結果看起來是這樣的:

Grouped flow document

+0

嗨,對不起在我的回覆延遲。非常感謝您的解決方案和清晰完整的解釋。它像一個魅力! – svr

0

您需要的是分組。它保持在MVVM規則中。

話雖如此,在流文檔上分組的快速谷歌並沒有立即顯示任何東西。也許看看flowdocument wpf分組。

一種解決方案可能是使用數據網格。你可以使用mvvm將它組合在一起,並使它看起來像你上面描述的佈局。