1

dotnetrdfを使用しており、クエリの結果を WPF で表示したいと考えています。これは ViewModel での私の関数です。ビューで次に使用する DataTable があります。

        //Results
        SparqlResultSet results;
        DataTable table;
        //Define a remote endpoint
        //Use the DBPedia SPARQL endpoint with the default Graph set to DBPedia
        SparqlRemoteEndpoint endpoint = new SparqlRemoteEndpoint(new Uri("http://dbpedia.org/sparql"), "http://dbpedia.org");

        //Make a SELECT query against the Endpoint
        results = endpoint.QueryWithResultSet("PREFIX dbo: <http://dbpedia.org/ontology/> PREFIX : <http://dbpedia.org/resource/> SELECT ?film ?producerName WHERE {    ?film dbo:director :Andrzej_Wajda .    ?film dbo:producer ?producerName . }");
        foreach (SparqlResult result in results)
        {
           Console.WriteLine(result.ToString());
        }

        table = new DataTable();
        DataRow row;

        switch (results.ResultsType)
        {
            case SparqlResultsType.VariableBindings:
                foreach (String var in results.Variables)
                {
                    table.Columns.Add(new DataColumn(var, typeof(INode)));
                }

                foreach (SparqlResult r in results)
                {
                    row = table.NewRow();

                    foreach (String var in results.Variables)
                    {
                        if (r.HasValue(var))
                        {
                            row[var] = r[var];
                        }
                        else
                        {
                            row[var] = null;
                        }
                    }
                    table.Rows.Add(row);
                }
                break;
            case SparqlResultsType.Boolean:
                table.Columns.Add(new DataColumn("ASK", typeof(bool)));
                row = table.NewRow();
                row["ASK"] = results.Result;
                table.Rows.Add(row);
                break;

            case SparqlResultsType.Unknown:
            default:
                throw new InvalidCastException("Unable to cast a SparqlResultSet to a DataTable as the ResultSet has yet to be filled with data and so has no SparqlResultsType which determines how it is cast to a DataTable");
        }

WPF では、次のコードを使用します。

<DataGrid ItemsSource="{Binding Table}" AutoGenerateColumns="True"/>

バインディングは非常にうまく機能し、最終的に動的に作成された列と DataGrid を取得しますが、ヘッダーのみを取得します。行の値が取得できません。この例では、行はありますが、値はありません。

ここに画像の説明を入力

私の問題はどこですか?助けてくれてありがとう:)

4

1 に答える 1

1

この質問は、開始データが SPARQL クエリからのものであることを除けば、dotNetRDF とはあまり関係ありませんが、実際には が であり、が使用されているDataGrid場合の動作に関するものです。ItemsSourceDataTableAutoGenerateColumns

基本的な問題は、DataGridが任意のデータ型を表示する方法を認識せず、自動生成された列に対してDataGridTextColumnを生成するだけであるということです。残念ながら、Stringこれは明示的に適用される値または型のみをサポートします。変換は双方向IValueConverterであることが予想されるため呼び出されませんToString()。したがって、空の列が表示されるのはなぜですか (これを説明するためのこの質問に感謝します)。

したがって、実際に値を適切に表示するには、DataTemplate使用する列を作成する必要があります。ただし、使用したい場合は、次のようAutoGenerateColumnsにイベントのハンドラーを追加する必要があります。AutoGeneratingColumns

<DataGrid ItemsSource="{Binding Table}" AutoGenerateColumns="True"
          AutoGeneratingColumn="AutoGeneratingColumn" />

次に、次のように、自動生成された各列に適切な列タイプを適用するイベント ハンドラーの実装を追加する必要があります。

private void AutoGeneratingColumn(object sender, System.Windows.Controls.DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.PropertyType != typeof (INode)) return;
    DataTableDataGridTemplateColumn column = new DataTableDataGridTemplateColumn();
    column.ColumnName = e.PropertyName;
    column.ClipboardContentBinding = e.Column.ClipboardContentBinding;
    column.Header = e.Column.Header;
    column.SortMemberPath = e.Column.SortMemberPath;
    column.Width = e.Column.Width;
    column.CellTemplate = (DataTemplate) Resources["NodeTemplate"];

    e.Column = column;
}

ここで特別な型を使用していることに注意してください。これは、よりわかりやすい名前に変更されたTemplateColumns を使用して WPF DataGrid を DataTable にバインドDataTableDataGridTemplateColumnする への回答からの単なるクラスです。

DataGridTemplateColumnを直接使用できない理由はDataTable、各列のテンプレートをバインドすると、特定の列の値ではなく行全体が渡されるため、特定の列の値のみをバインドしてテンプレートが書式設定されるようにクラスを拡張する必要があるためです。INode行全体ではなく、行内のその列の実際の値。

最後に、列が適切にフォーマットされるように、XAML で参照したテンプレートを定義する必要があります。

<Window.Resources>
    <sparqlResultsDataGridWpf:MethodToValueConverter x:Key="MethodToValueConverter" />
    <DataTemplate x:Key="NodeTemplate" DataType="rdf:INode">
        <TextBlock Text="{Binding Converter={StaticResource MethodToValueConverter}, ConverterParameter='ToString'}"/>
    </DataTemplate>
</Window.Resources>

ここで値コンバーターも定義したことに注意してください。これMethodToValueConverterBind to a method in WPF? の回答から取られていますか? 任意の型のメソッド呼び出しの結果を単純に取得し、これを表示値として使用できます。ここで、テンプレートの構成はToString()、基礎となるINodeインスタンスを呼び出すだけです。

これらすべてを実装して、サンプルクエリを実行すると、 my に次のように表示されますDataGrid

ここに画像の説明を入力

使用したコードはすべてhttps://bitbucket.org/rvesse/so-23711774で見つけることができます

INodeこの基本的なアプローチを使用して、必要に応じて多くの視覚的なベルとホイッスルを備えた、はるかに堅牢なレンダリングを構築できます。

サイドノート

この回答に関連するいくつかのメモ。まず、部分的な XAML とコード フラグメントではなく、コードの最小限の完全な例を投稿した方が、はるかに簡単に作成できたはずです。

第二に、dotNetRDFSparqlResultSetクラスは実際にはすでに defined への明示的なキャストを持っているため、たとえばの構造を制御したい場合を除きDataTable、手動で自分自身に変換する必要はありません。DataTableDataTable

DataTable table = (DataTable) results;
于 2014-05-19T14:51:03.160 に答える