我最终使用了附加属性解决方案。它非常干净,不会“污染”现有代码。您只需添加一行 XAML(见下文)即可将导出到 excel 功能添加到任何数据网格。
<igDP:XamDataGrid
x:Name="summary"
Behaviours:XamDataGridBehaviours.ExportFileName="plop.xls"
ActiveDataItem="{Binding Path=SelectedSummary}">
[...]
</igDP:XamDataGrid>
附加的属性代码本身如下:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using Infragistics.Documents.Excel;
using Infragistics.Windows.DataPresenter;
using Infragistics.Windows.DataPresenter.ExcelExporter;
using Microsoft.Win32;
namespace MYCOMPANY.Plugin.Framework.Behaviours
{
public class XamDataGridBehaviours
{
public static readonly DependencyProperty ExportFileNameProperty = DependencyProperty.RegisterAttached(
"ExportFileName",
typeof(string),
typeof(XamDataGridBehaviours),
new FrameworkPropertyMetadata(OnExportCommandChanged));
private const string ExportToExcelHeader = "Export to Excel";
[AttachedPropertyBrowsableForType(typeof(XamDataGrid))]
public static string GetExportFileName(XamDataGrid d)
{
return (string)d.GetValue(ExportFileNameProperty);
}
public static void SetExportFileName(XamDataGrid d, string value)
{
d.SetValue(ExportFileNameProperty, value);
}
static void OnExportCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = d as XamDataGrid;
var fileName = (string) e.NewValue;
if (grid != null && !string.IsNullOrEmpty(fileName))
{
CreateExcelExportMenu(grid, fileName);
}
else if (grid != null && grid.ContextMenu != null)
{
SafeDeleteMenuItem(grid.ContextMenu);
}
}
private static void CreateExcelExportMenu(XamDataGrid grid, string fileName)
{
var contextMenu = grid.ContextMenu ?? new ContextMenu();
var exportToExcel = GetOrCreateMenuItem(grid, contextMenu, fileName);
contextMenu.Items.Add(exportToExcel);
grid.ContextMenu = contextMenu;
}
private static void ExportToExcel(XamDataGrid grid, string fileName)
{
var saveFileDialog = new SaveFileDialog();
saveFileDialog.FileName = fileName;
saveFileDialog.DefaultExt = ".xls";
saveFileDialog.Filter = "Excel spreadsheets (.xls)|*.xls";
if (saveFileDialog.ShowDialog() == true)
{
var exporter = new DataPresenterExcelExporter();
exporter.Export(grid, saveFileDialog.FileName, WorkbookFormat.Excel97To2003);
}
}
private static MenuItem GetOrCreateMenuItem(XamDataGrid grid, ContextMenu menu, string fileName)
{
foreach (var item in menu.Items)
{
if (item is MenuItem)
{
var menuitem = item as MenuItem;
if (menuitem.Header.ToString() == ExportToExcelHeader)
{
menuitem.Command = new RelayCommand(o => ExportToExcel(grid, fileName));
return menuitem;
}
}
}
var exportToExcel = new MenuItem();
exportToExcel.Header = ExportToExcelHeader;
exportToExcel.Command = new RelayCommand(o => ExportToExcel(grid, fileName));
var icon = new Image();
var bmImage = new BitmapImage();
bmImage.BeginInit();
bmImage.UriSource = new Uri(@"..\..\Images\excel.png", UriKind.RelativeOrAbsolute);
bmImage.EndInit();
icon.Source = bmImage;
icon.MaxWidth = 16;
exportToExcel.Icon = icon;
return exportToExcel;
}
private static void SafeDeleteMenuItem(ContextMenu menu)
{
MenuItem toDelete = null;
foreach (var item in menu.Items)
{
if (item is MenuItem)
{
var menuitem = item as MenuItem;
if (menuitem.Header.ToString() == ExportToExcelHeader)
{
toDelete = menuitem;
break;
}
}
}
if (toDelete != null)
menu.Items.Remove(toDelete);
}
}
}
如您所见,每当我们为网格设置一个非空的导出文件名时,代码都会添加一个导出到 excel 项。如果文件名最终为 null,则代码将尝试删除导出项(如果存在)。这样,它不应该阻止 xaml 设置其他项目,并且应该保持透明。