table of data

I need to display the contents of an XML file in tabular form. The basic structure of the XML is;

<table>
<row>
<column_name_1 />
...
<column_name_n />
</row>
</table>

where column_name_* etc could be <name>, <age>, etc. For example,

<table>
<row>
<name>Bob</name>
<age>32</age>
</row>
<row>
<name>Alice</name>
<age>23</age>
</row>
</table>

Which should result in a table thus,

[name][age]
Bob 32
Alice 23

Unfortunately, what I am seeing is

[name][age]
32 32
23 23

Obviously, my binding logic is wrong.

In the Xaml I have created the following resources;

<XmlDataProvider x:Key="TableModel" />

<DataTemplate x:Key="TableCellTemplate">
<Grid>
<Label>
<TextBlock Text="{Binding XPath=text()}"/>
</Label>
</Grid>
</DataTemplate>

and the following ListView;

<ListView ItemsSource="{Binding Source={StaticResource TableModel}}">
<ListView.View>
<GridView x:Name="GV">
<GridView.Columns />
</GridView>
</ListView.View>
</ListView>

In the C# I grab the XmlDataProvider and add my XmlDocument to it before programatically creating the columns thus;

XmlElement docElement = xml.Document.DocumentElement;
XmlElement rowElement = (XmlElement)docElement.ChildNodes[0];

foreach (XmlElement element in rowElement.ChildNodes)
{
xml.XPath = "//" + element.Name;
GridViewColumn column = new GridViewColumn();
column.Header = element.Name;
column.CellTemplate = (DataTemplate)FindResource("TableCellTemplate");
GV.Columns.Add(column);
}

I believe my XPath statements are wrong. Can anybody help


Answer this question

table of data

  • Rijckewaert

    Hi,

    thanks for replying. However, I already have the solution to this problem.

    But thanks again.

    Barry

  • Swami

    The only way I cna think of is to create the template in Xaml as I have done and traverse the template's VisualTree in the C# whe I'm creating the columns and set the binding then.

  • Shruthi

    Two things:

    1. You need to set the XPath of your ItemsSource binding to /table/row. This will cause the ListView to bind to each of the <row> elements.
    2. The XPath binding for your GridViewColumn should then simply need to be the name of the child element the column represents. (i.e. xml.XPath = element.Name)

    I'm not 100% sure what type the "xml" variable is in your sample. I'm assuming it's a Binding instance, but since you're not constructing it per column it kinda worries me that you're somehow reusing the same Binding instance for each column which I would think would also cause problems.

    Try that and lemme know how it works out.

    HTH,
    Drew


  • Mohamed Harris

    I don't think there is a way to change the data source of the column other than through the CellTemplate property and I think I may have to do this in the C# as in my earlier post to this forum.
  • pkellner

    Does anybody know how to create a Binding object to an XML Document and add it as the binding of a DataTemplate's VisualTree in C#


  • Andretti Fan

    Hi,

    Let me repeat you purpose first:

    You wanted to change the content that a column shows, but did not want to change celltemplate on column. So, you created column by code and attempted to change binding on celltemplate dynamically by code. Am I right

    1. CellTemplate on column is the recommended way to change content a column shows. So, you should use CellTemplate as much as possible, do you have any concerns CellTemplate or CellTemplateSelector here

    2. CellTemplate is of type DataTemplate, you can find the type of DataTemplate.VisualTree is FrameworkElementFactory, which acts as a template, it can be not changed dynamically once it is created. So, it is almost impossilbe for you to maintail CellTemplate programatically.

    3. Ok, you may you can change the binding on DataTemplate to realize your idea. Similiarly, I strongly disencourage you to do this.

    4. As for "how to create a Binding object to an XML Document and add it as the binding of a DataTemplate's VisualTree in C#", hope the following code helps:

    DataTemplate dt = new DataTemplate();

    fef = new FrameworkElementFactory(typeof(Button));

    Binding binding = new Binding();

    binding.XPath = "PropertyName";

    fef.SetBinding(Button.ContentProperty, binding);

    dt.VisualTree = fef;

    column.CellTemplate = dt;

    However, if you want to change column dynamically, use CellTemplate or CellTemplateSelector;



  • AntiRules

    Hi,

    If I set the ItemsSource thus,

    ItemsSource="{Binding Source={StaticResource TableModel}, XPath=/table/row}"

    and

    column.DisplayMemberPath = element.Name

    then the table displays the data correctly.

    Unfortunately, with the following DataTemplate,

    <DataTemplate x:Key="TableCellTemplate">
    <Grid>
    <Label>
    <TextBlock Text="{Binding XPath=text()}"/>
    </Label>
    </Grid>
    </DataTemplate>

    and

    column.CellTemplate = (DataTemplate)FindResource("TableCellTemplate");

    a table with two columns and two rows iscreated but its cells are empty. This why I left the XPath expression off the ItemsSource in my original post and created the XPath expression each time I created a column in my original example.

    You asked what xml is. It is the XmlDataProvider.

    XmlDataProvider xml = (XmlDataProvider)FindResource("TableModel");

    It is to this I add my XML document,

    xml.Document = <... XML to be displayed ..>

    and my XPath expression when creating the table.

    xml.XPath = "//" + element.Name;

    There is no longer a Binding object being created.

    Regards,

    Barry

  • Bryan Hinton

    It's unfortunately lookin' like that, but I'm trying to figure out a way that you can maintain your template in XAML and simply set the right binding on it at runtime. It would really suck to have to hardcode your template in C# for a myriad of reasons.

    Cheers,
    Drew


  • Theodore C

    I see the problem. You definitely don't want to change the XPath of the XmlDataProvider, that needs to stay /table/row. The problem is that the template's binding is to text() because I expected there to be a way to change the datasource of the GridViewColumn as your building them programatically to be the element for the speicific column, but there doesn't appear to be a way to do that. I'll see what I can come up with...

    Later,
    Drew


  • table of data