I'm fairly new to WPF and was wondering whether a possibility exists to simply export a WPF DataGrid to a csv file. I've tried using reflections to get the values needed, though that works to some extent I was wondering whether it's possible with an attached property to get the displayed values, these do not necessarily correspond to the values of the item source. The below attached property works as long as I use a static string, or a static resource of a string etc. If I try to use the columns bindings I just get a the default string.empty
public static readonly DependencyProperty ExportStringProperty =
DependencyProperty.RegisterAttached("ExportString", //name of attached property
typeof(string), //type of attached property
typeof(ExportBehaviour), //type of this owner class
new PropertyMetadata(string.Empty)); //the default value of the attached property
public static string GetExportString(DataGridColumn column)
{
return (string)column.GetValue(ExportStringProperty);
}
public static void SetExportString(DataGridColumn column, string value)
{
column.SetValue(ExportStringProperty, value);
}
Is there a similar way to get the binding value from xaml in a way like:
<DataGridTextColumn Header="Name" Binding="{Binding (datagridexcel:Product.Name)}" datagridexcel:ExportBehaviour.ExportString="{Binding (datagridexcel:Product.Name)}"/>
as said, the above earlier works for a static typed string and not for the binding. It has to be said that working with the item source in this case should be avoided and the only thing I'm interested in is the datagrid and the values shown there.
I made this simple app to demonstrate a way of getting CSV from DataGrid
.
You have the DataGrid
:
<DataGrid x:Name="MyDataGrid" Grid.Row="0" ItemsSource="{Binding Rows}" />
In this example it's bound to the following property in the viewmodel:
private IEnumerable<RowViewModel> _rows;
public IEnumerable<RowViewModel> Rows
{
get { return _rows; }
set
{
_rows = value;
OnPropertyChanged("Rows");
}
}
Rows are set to the following sample data:
Rows = new List<RowViewModel>
{
new RowViewModel { FirstName = "John", LastName = "Doe", DateOfBirth = new DateTime(1988, 12, 19) },
new RowViewModel { FirstName = "Lara", LastName = "Croft", DateOfBirth = new DateTime(1975, 5, 3) },
new RowViewModel { FirstName = "Sam", LastName = "Fisher", DateOfBirth = new DateTime(1967, 2, 9) }
};
Under the DataGrid
I have a Button
:
<Button Grid.Row="1" Content="Copy values as CSV" Command="{Binding CopyAsCsvCommand}" CommandParameter="{Binding ElementName=MyDataGrid}" />
It's bound to a Command
in the viewmodel and the CommandParameter
is the whole DataGrid
.
CopyAsCsvCommand = new DelegateCommand<DataGrid>(CopyAsCsvHandler);
The Command
's handler method where the actual copying happens:
private void CopyAsCsvHandler(DataGrid dg)
{
dg.SelectAllCells();
dg.ClipboardCopyMode = DataGridClipboardCopyMode.IncludeHeader;
ApplicationCommands.Copy.Execute(null, dg);
dg.UnselectAllCells();
LivePreviewText = (string)Clipboard.GetData(DataFormats.CommaSeparatedValue);
}
This is equivalent to selecting all the cells with CTRL+A and pressing CTRL+C.
Example
Now that you have the CSV content you can just save it down to a file with CSV extension. I hope this helps and this is what you were looking for.