简体   繁体   中英

How can I export a DataGrid to XML in WPF application?

I have a DataGrid called GokartDataGrid. It has some columns and rows, and I would like to export the table into an XML file, but the method I found giving an exception for me. My code is looks like this, and it says System.InvalidCastException at the DataTable instantiation.

private void Xml_export() 
{
    DataTable dt = (DataTable)GokartDataGrid.ItemsSource;
    SaveFileDialog savefile = new SaveFileDialog();
    savefile.Filter = "XML |*.xml";
    savefile.ShowDialog();
    savefile.CheckFileExists = true;
    savefile.CheckPathExists = true;
    dt.WriteXml(savefile.FileName);         
}

I will make a try-catch section after it works, but right now I don't know what can I do.
What should I do to make it work? Okay so here is the upload of the datagrid.

    public void DataGridUpload(string filepath)
    {
        if (filepath != null) 
        { 
        Gokart_container minden = new Gokart_container(filepath);
        GokartDataGrid.ItemsSource = minden.GetGokartlist();
        }
    }

The Gokart_container contains Gokart objects in a list and the Gokart object has a few datas in it like best lap time and all laps in an other list. And some strings like racer name.

The datagrid.Columns can give you the column header order. And the datagrid.Items.SourceCollection the row values. And you go from there.

I don't know for sure what it is, but that error is saying you don't have a datatable as an itemssource.
Which is doubly true.

Your ItemsSource cannot be a datatable.
If I try setting the itemssource of a datagrid to one I get the error:

Cannot implicitly convert type 'System.Data.DataTable' to 'System.Collections.IEnumerable'. An explicit conversion exists (are you missing a cast?)

So I don't know what GetGokartlist() returns, but it isn't a datatable. You could possibly be using the defaultview of a datatable. Because this works:

dg.ItemsSource = dt.DefaultView;

If I then do a gettype to check what that is:

Type isType = dg.ItemsSource.GetType();

It's a DataView rather than a datatable.

Maybe you could cast to dataview and work with that. But maybe that's not what you have anyhow.

But you say Gokart objects in a List.
Which sounds like a List.
So you could possibly cast to List

But casting some data you get back out the front end when you gave the datagrid that data in the first place is an unusual way to work.

It's more usual to work with wpf using MVVM.
Like this:
https://social.technet.microsoft.com/wiki/contents/articles/32164.wpf-mvvm-step-by-step-2.aspx

With MVVM you'd have a viewmodel which retains a reference to the collection of GoKart. This would usually be an observablecollection rather than a List. An observablecollection raises collection changed when you add or remove an item which is useful AND the datagrid loses some functionality if you bind to a List.

Anyhow, this way you'd have a reference to the collection of data and can work with that directly.
How about xml from a List ?
Often it's not just the one property you want to serialise, there's a whole load of them.
You could create a class which has one property, a List and fill that from your observablecollection using Linq and .ToList().
You then just serialise that class and you have all your data as xml.
Just make your class public, the properties public and use datacontractserialiser.

Here's an example bit of code which serialises to disk and deserialises back:

    public static void SaveScenario(string fileURL, Scenario scenario)
    {
        scenario.ScenarioFile = fileURL;
        using (FileStream writer = new FileStream(fileURL, FileMode.Create))
        {
            DataContractSerializer ser = new DataContractSerializer(typeof(Scenario));
            ser.WriteObject(writer, scenario);
        } 
    }
    public static Scenario ReadScenario(string fileURL)
    {
        FileStream fs = new FileStream(fileURL, FileMode.Open);
        XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
        DataContractSerializer ser = new DataContractSerializer(typeof(Scenario));
        Scenario deserializedScenario = (Scenario)ser.ReadObject(reader, true);
        reader.Close();
        fs.Close();
        return deserializedScenario;
    }
}   

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM