将Generic Xml绑定到Datagrid

时间:2016-06-01 08:20:29

标签: c# xml wpf binding datagrid

我有一组xml文件。 文件总是这样构建:

<?xml version="1.0" encoding="UTF-8"?>
<Data>
  <Row>
    <halfproducten ID="105">Digitale bestanden van papieren zeekaarten en 1800 serie</halfproducten>
    <formaat ID="106">PDF, PS, SHAPE, CARIS NTX/ASCII*, GEOTIFF, S57*</formaat>
    <datum_validiteit ID="107">Meest recente editie</datum_validiteit>
    <geografische_grenzen ID="108">Karteringsgebied</geografische_grenzen>
  </Row>
  <Row>
    <halfproducten ID="109">Fragmenten van bovengenoemde bestanden</halfproducten>
    <formaat ID="110">PDF, PS, SHAPE, CARIS NTX/ASCII*, GEOTIFF, S57*</formaat>
    <datum_validiteit ID="111">Meest recente editie</datum_validiteit>
    <geografische_grenzen ID="112">Karteringsgebied</geografische_grenzen>
  </Row>
  <Row>
    <halfproducten ID="113">Minuutbladen</halfproducten>
    <formaat ID="114">Papier</formaat>
    <datum_validiteit ID="115">
    </datum_validiteit>
    <geografische_grenzen ID="116">Karteringsgebied</geografische_grenzen>
  </Row>
  <Row>
    <halfproducten ID="117">Tracings</halfproducten>
    <formaat ID="118">PDF</formaat>
    <datum_validiteit ID="119">Meest recent</datum_validiteit>
    <geografische_grenzen ID="120">Karteringsgebied</geografische_grenzen>
  </Row>
  <Row>
    <halfproducten ID="121">Bathymetrie-bestanden</halfproducten>
    <formaat ID="122">ASCII, x-y-z (20 x 20)</formaat>
    <datum_validiteit ID="123">Meest recent</datum_validiteit>
    <geografische_grenzen ID="124">Karteringsgebied</geografische_grenzen>
  </Row>
  <Row>
    <halfproducten ID="125">Object-selecties data bestanden:;Wrakken/Obstructies;Lichten;Boorplatforms/Boorputten;Boeien/Bakens</halfproducten>
    <formaat ID="126">Papier, ASCII, HOB, S57, SHAPE, GEOTIFF, GML</formaat>
    <datum_validiteit ID="127">Actueel</datum_validiteit>
    <geografische_grenzen ID="128">Nederlands Continentaal Plat + Territoriale zee</geografische_grenzen>
  </Row>
  <Row>
    <halfproducten ID="129">Maritieme (zone)grenzen (UNCLOS)</halfproducten>
    <formaat ID="130">ASCII, SHAPE, KML</formaat>
    <datum_validiteit ID="131">Actueel</datum_validiteit>
    <geografische_grenzen ID="132">Continentaal Plat + Territoriale zee van Nederland, het Caraibisch deel van het Koninkrijk der Nederlanden</geografische_grenzen>
  </Row>
</Data>

这里始终存在数据和行元素,标记元素始终是不同的标记名,标记的数量总是不同的。 只有Row元素都具有相同的子元素,只有不同的文本。

我想将这个xml文件绑定到我的DataGrid,这样如果在DataGrid中更改了somthing,它会自动在xml文件中更改。

到目前为止我有这个:

<Grid.DataContext>
<XmlDataProvider x:Name="xmlDataProvider"/>
</Grid.DataContext> 

(我的DataGrid在网格中)

<DataGrid AutoGenerateColumns="True" Name="DataGridXml" SelectionMode="Extended"
SelectionUnit="CellOrRowHeader" CanUserSortColumns="False"
CanUserReorderColumns="False" CanUserAddRows="False" CanUserDeleteRows="False"
VirtualizingStackPanel.IsVirtualizing="False" ItemsSource="{Binding}">

代码隐藏:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(path);
XmlDataProvider dataProvider = xmlDataProvider;
dataProvider.Document = xmlDoc;
dataProvider.XPath = "Data/Row";

使用上述所有代码,我的解决方案可以工作,它也绑定到我的数据网格,只是它绑定到Xml-Element的属性,而不是将标记绑定到列。

所以要明确,我想要的是这个:

__________________________________________
|     Tag1    |    Tag2     |    Tag3     |
|-------------|-------------|-------------|
|Lerum Ipsum11|Lerum Ipsum12|Lerum Ipsum13|
|-------------|-------------|-------------|
|Lerum Ipsum21|Lerum Ipsum22|Lerum Ipsum23|
|-------------|-------------|-------------|

先谢谢你帮助我;)

1 个答案:

答案 0 :(得分:1)

使用DataGird列定义,如:

<DataGrid AutoGenerateColumns="False"  Name="DataGridXml" SelectionMode="Extended" DataContext="{Binding dataProvider}"
            SelectionUnit="CellOrRowHeader" CanUserSortColumns="False"
            CanUserReorderColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" 
            VirtualizingStackPanel.IsVirtualizing="False" ItemsSource="{Binding XPath=/Data/Row}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Tag1" Binding="{Binding XPath=tag1/.}" />
        <DataGridTextColumn Header="Tag2" Binding="{Binding XPath=tag2/.}" />
        <DataGridTextColumn Header="Tag3" Binding="{Binding XPath=tag3/.}" />
    </DataGrid.Columns>

</DataGrid>

<强> 输出:

XML Bind

PS:我还更改了DataContext作业和AutoGenerateColumn属性。并使dataProvider成为property,这是代码中的方法变量。

更新:如果想要从DataGrid 生成Columns XML

<强> XMAL:

<DataGrid AutoGenerateColumns="False"  Name="DataGridXml" SelectionMode="Extended" DataContext="{Binding dataProvider}"
        SelectionUnit="CellOrRowHeader" CanUserSortColumns="False"
        CanUserReorderColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" 
        VirtualizingStackPanel.IsVirtualizing="False" ItemsSource="{Binding}"
        local:XMLToColumn.GenerateColumnForGrid="True"/>

附加行为:

public class XMLToColumn
{
    public static bool GetGenerateColumnForGrid(DependencyObject obj)
    {
        return (bool)obj.GetValue(GenerateColumnForGridProperty);
    }

    public static void SetGenerateColumnForGrid(DependencyObject obj, bool value)
    {
        obj.SetValue(GenerateColumnForGridProperty, value);
    }

    // Using a DependencyProperty as the backing store for GenerateColumnForGrid.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty GenerateColumnForGridProperty =
        DependencyProperty.RegisterAttached("GenerateColumnForGrid", typeof(bool), typeof(XMLToColumn), new PropertyMetadata(GenerateColumnForGridChanged));

    public static void GenerateColumnForGridChanged(DependencyObject DO, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = DO as DataGrid;
        if (dataGrid != null && Convert.ToBoolean(e.NewValue) == true)
        {
            dataGrid.Loaded += dataGrid_Loaded;
        }
    }

    static void dataGrid_Loaded(object sender, RoutedEventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid != null)
        {
            dataGrid.Columns.Clear();
            var dataprovider = dataGrid.DataContext as XmlDataProvider;
            if (dataprovider != null)
            {
                var mainNode = dataprovider.Document.SelectSingleNode(dataprovider.XPath);
                foreach (var item in mainNode.ChildNodes)
                {
                    var node=item as XmlNode;
                    var column = new DataGridTextColumn();
                    column.Binding = new Binding() { XPath = node.Name+"/." };
                    column.Header = node.Name;
                    dataGrid.Columns.Add(column);
                }
            }
        }
    }

}

<强> 输出:

XML

ID问题更新:

public class XMLToColumn
{
    public static bool GetGenerateColumnForGrid(DependencyObject obj)
    {
        return (bool)obj.GetValue(GenerateColumnForGridProperty);
    }

    public static void SetGenerateColumnForGrid(DependencyObject obj, bool value)
    {
        obj.SetValue(GenerateColumnForGridProperty, value);
    }

    // Using a DependencyProperty as the backing store for GenerateColumnForGrid.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty GenerateColumnForGridProperty =
        DependencyProperty.RegisterAttached("GenerateColumnForGrid", typeof(bool), typeof(XMLToColumn), new PropertyMetadata(GenerateColumnForGridChanged));

    public static void GenerateColumnForGridChanged(DependencyObject DO, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = DO as DataGrid;
        if (dataGrid != null && Convert.ToBoolean(e.NewValue) == true)
        {
            dataGrid.Loaded += dataGrid_Loaded;               
            dataGrid.RowEditEnding += new EventHandler<DataGridRowEditEndingEventArgs>(dataGrid_RowEditEnding);
        }
    }

    static void dataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
    {
         var dataGrid = sender as DataGrid;
         if (dataGrid != null)
         {                 
             var dataprovider = dataGrid.DataContext as XmlDataProvider;
             if (dataprovider != null)
             {
                 if (e.Row.GetIndex() == dataGrid.Items.Count - 1)
                 {
                     int maxID = Convert.ToInt32(dataprovider.Document.LastChild.LastChild.LastChild.Attributes["ID"].Value);
                     var rowElement = dataprovider.Document.CreateElement("Row");
                     foreach (var col in dataGrid.Columns)
                     {
                         var childElement = dataprovider.Document.CreateElement(col.Header.ToString());
                         childElement.SetAttribute("ID",(++maxID).ToString());
                         rowElement.AppendChild(childElement);                             
                     }
                     dataprovider.Document.DocumentElement.AppendChild(rowElement);
                     e.Cancel = true;
                 }
             }
         }            
    }        

    static void dataGrid_Loaded(object sender, RoutedEventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid != null)
        {
            dataGrid.Columns.Clear();
            var dataprovider = dataGrid.DataContext as XmlDataProvider;
            if (dataprovider != null)
            {
                var mainNode = dataprovider.Document.SelectSingleNode(dataprovider.XPath);
                foreach (var item in mainNode.ChildNodes)
                {
                    var node = item as XmlNode;
                    var column = new DataGridTextColumn();
                    column.Binding = new Binding() { XPath = node.Name + "/." };
                    column.Header = node.Name;
                    dataGrid.Columns.Add(column);
                }
            }
        }
    }

}

一旦您结束编辑最后一行的最后一个单元格,该行为就会在您的row中添加新的datagrid。代码也非常依赖于您的XML限制。请仔细看看。

<强> 输出:

output