2012-07-31 23 views
0

我對WPF相當陌生,並且對於同一類型的所有控件中的邏輯的「因式分解」存在疑問。爲給定控件類型的任何實例創建一個ContextMenu

更準確地說,對於Infragistrics DataGrid的任何實例,我想要一個帶有「導出到Excel」按鈕的上下文菜單,而不必在每次使用該網格時都編寫任何代碼。 此外,如果默認情況下,我將始終有一個「導出到Excel」上下文菜單項,我也希望能夠根據具體情況透明地添加更多項目。 獎勵將能夠刪除特定實例上的導出到Excel按鈕。

我的問題是什麼是實現這一目標的最佳途徑:

  • 子類在DataGrid和「OnInitialized」 programmaticaly添加文本菜單?問題:如何在網格中添加額外的菜單項...... XAML將覆蓋已有的內容?此外,我寧願不要有我的控件的子類,只是直接使用控件本身,並使用WPF來添加預期的行爲。
  • 使用「行爲」?我可以添加一個新的附加屬性到這種類型的網格,但不知道這是一個好的做法
  • 還有其他嗎?

我希望我的問題有道理!

注意:這個問題不是關於導出到Excel,我知道如何與我的控制做到這一點。

回答

0

創建List<MenuItem> DependencyProperty(如果你想從ViewModel綁定。如果你只是想從代碼分配背後則創建簡單的CLR屬性)在您的DataGrid控件和綁定/將其分配到的額外menuItems列表。並在event DataGridLoaded事件將這些額外的menuItems添加到Common MenuItems.I希望這會有所幫助。

+0

感謝您的回答!儘管我想盡可能減少對現有控制的干擾(即我不想改變現有的「頁面」),但這並不是我想要的。我最終使用了附加的屬性解決方案,我將在下面發佈我的解決方案。 – 2012-07-31 09:14:06

0

我最終使用了附加的屬性解決方案。它非常乾淨,不會「污染」現有的代碼。您只需添加一行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項目。如果文件名最終爲空,則代碼將嘗試刪除導出項目(如果存在)。這樣,它不應該阻止其他項目由XAML設置,並應保持透明。

0

如果您在XAML做到這一點,你做CAND:

<DataGrid> 
    <DataGrid.ContextMenu> 
    <!--Binding to your view model and the command is whatever your command name should be -> 
    <MenuItem Header="Export to CSV" Command="{Binding Export}"/> 
    </DataGrid.ContextMenu> 
</DataGrid> 

這允許您對新對象添加到右鍵菜單。

相關問題