2

私のMVVMWPFアプリケーションでは、データバインドされたフロードキュメントを使用しています。ここで説明する手法を使用して、データをフロードキュメントにバインドできるようにしました。フロードキュメントは、ビューモデルのパブリックプロパティにバインドされています。プロパティは、次のようなカスタムタイプの無数のプロパティです。

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

フロードキュメントは、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ルールに違反せずにこれを行う方法に関する提案はありますか?フロードキュメントのデータバインディングには、柔軟性のないレイアウトという代償が伴うようです。

前もって感謝します

4

2 に答える 2

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

変更されたコードの機能は次のとおりです。アイテムのソースがコレクションビューでない場合は、元のMSDNコードとまったく同じように機能します。アイテムソースがコレクションビューの場合、2つのネストされたループが呼び出されます。

  • 外側のループはすべてのグループを繰り返します。
  • 内側のループは、現在のグループ内のすべてのアイテムを繰り返し処理します。

内側のループは、MSDNの記事にある元のforeachループと実質的に同じです。

上記の追加コードでは、空のテーブル行が次の行によって追加されています。

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

もちろん、このコードはあまり一般的ではありません。一般的なソリューションの場合、またはプロパティItemsContentと同様に、データテンプレートを含むコントロールに新しい依存関係プロパティを追加します。次に、グループの最後に任意のテキストを挿入することができます。ItemsPanelItemTemplate

結果は次のようになります。

グループ化されたフロードキュメント

于 2012-07-05T07:12:13.513 に答える
0

必要なのはグループ化です。MVVMルールの範囲内にとどまります。

そうは言っても、フロードキュメントをグループ化するための簡単なグーグルはすぐには何も表示しませんでした。たぶん、flowdocumentwpfのグループ化を見て回ってください。

1つの解決策は、データグリッドを使用することです。あなたは間違いなくmvvmでそれをグループ化し、それをあなたが上で説明したレイアウトのように見せることができます。

于 2012-07-05T06:01:54.370 に答える