最終的には、添付プロパティ ソリューションを使用しました。非常にクリーンで、既存のコードを「汚染」しません。XAML を 1 行追加するだけで (以下を参照)、export to 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);
}
}
}
ご覧のとおり、null 以外のエクスポート ファイル名をグリッドに設定すると、コードは Excel アイテムへのエクスポートを追加します。ファイル名が null になった場合、コードはエクスポート項目が存在する場合はそれを削除しようとします。このようにして、xaml によって他の項目が設定されるのを妨げず、透過性を維持する必要があります。