2011-04-02 38 views
3

我將xaml中的三個相關但不同的DataGrid重構爲代碼並觸發更新上下文菜單的標題文本的問題。在代碼中創建上下文菜單

命令和文本需要根據哪個數據網格單元格是當前單元格進行更新。標題文本在xaml中更新得很好,但正如您從下面的圖片中看到的那樣,它現在顯示爲空字符串。該命令本身確實正常工作,並在正確的網格單元上工作。

標題文本的設置器觸發屬性發生了更改,但我懷疑我的代碼沒有按照與xaml等效的方式複製綁定。我也不確定Shared屬性是否需要在代碼中進行說明。

有沒有人看到我可以改進我使用的代碼?

乾杯,
Berryl

enter image description here

XAML風格建立綁定

<ContextMenu x:Key="NonProjectActivityContextMenu" x:Shared="true"> 

    <MenuItem 
     DataContext="{Binding MakeEachWeekDayFullDayCommand}" Command="{Binding .}" 
     Header="{Binding HeaderText}" InputGestureText="{Binding InputGestureText}"  
     /> 
    <MenuItem 
     DataContext="{Binding MakeFullDayCommand}" Command="{Binding .}" 
     Header="{Binding HeaderText}" InputGestureText="{Binding InputGestureText}"  
     /> 
</ContextMenu> 

<!-- Bindings assumes a VmMenuItem (Command Reference) --> 
<Style x:Key="ContextMenuItemStyle" TargetType="{x:Type MenuItem}"> 
    <Setter Property="Header" Value="{Binding HeaderText}"/> 
    <Setter Property="InputGestureText" Value="{Binding InputGestureText}" /> 
    <Setter Property="Command" Value="{Binding Command}" /> 
    <Setter Property="Icon" Value="{Binding Icon}" /> 
    <Setter Property="Tag" Value="{Binding IdTag}" /> 
    <Setter Property="ItemsSource" Value="{Binding Children}"/> 
</Style> 

CODE

protected virtual ContextMenu _GetContextMenu() { 
     var menuItems = _dataContext.MenuItems.Select(menuItem => menuItem.ToMenuItem()); 
     var cm = new ContextMenu(); 
     foreach (var item in menuItems) { 
      cm.Items.Add(item); 
     } 
     return cm; 
    } 

UPDATE

那麼空的字符串部分只是我自己的愚蠢 - 我沒有初始化標題文本!下面的圖片是我現在得到的,這是一個改進。文本應該更新說周壽的日子,即「讓週一一整天」 enter image description here

編輯艾爾諾

我設置列和網格本身如下的風格,所以我以爲我可以獲取上下文菜單的資源並進行設置。

然而,我們得到了一個奇怪的結果,就像你從圖片中看到的那樣 - 就像上下文菜單覆蓋了整個網格!

enter image description here

private void OnDataGridLoaded(object sender, RoutedEventArgs e) 
    { 
     _dataContext = (ActivityCollectionViewModel)DataContext; 

     IsSynchronizedWithCurrentItem = true; 
     Style = (Style)FindResource(GRID_STYLE_NAME); 

     _AddColumns(); 

     var timeSheetColumns = Columns.Cast<TimesheetGridColumn>(); 
     foreach (var col in timeSheetColumns) 
     { 
      col.SetHeader(); 
      col.SetCellStyle(this); 
      col.SetBinding(); 
     } 

     if(DesignerProperties.GetIsInDesignMode(this)) { 
      // just so the designer doesn't hit a null reference on the data context 
      ItemsSource = new ObservableCollection<ActivityViewModel>(); 
     } 
     else { 
      // ok, we have a runtime data context to work with 
      ItemsSource = _dataContext.ActivityVms; 
      InputBindings.AddRange(_GetKeyBindings()); 
      ContextMenu = _GetContextMenu(); 
      ContextMenu.Style = (Style)FindResource("ContextMenuItemStyle"); 
     } 
    } 


    private void OnDataGridLoaded(object sender, RoutedEventArgs e) 
    { 
     _dataContext = (ActivityCollectionViewModel)DataContext; 

     IsSynchronizedWithCurrentItem = true; 
     Style = (Style)FindResource(GRID_STYLE_NAME); 

     _AddColumns(); 

     var timeSheetColumns = Columns.Cast<TimesheetGridColumn>(); 
     foreach (var col in timeSheetColumns) 
     { 
      col.SetHeader(); 
      col.SetCellStyle(this); 
      col.SetBinding(); 
     } 

     if(DesignerProperties.GetIsInDesignMode(this)) { 
      // just so the designer doesn't hit a null reference on the data context 
      ItemsSource = new ObservableCollection<ActivityViewModel>(); 
     } 
     else { 
      // ok, we have a runtime data context to work with 
      ItemsSource = _dataContext.ActivityVms; 
      InputBindings.AddRange(_GetKeyBindings()); 
      ContextMenu = _GetContextMenu(); 
      ContextMenu.Style = (Style)FindResource("ContextMenuItemStyle"); 
     } 
    } 

最新

我試圖使每this SO post我相結合,但沒有骰子。我的命令已更新,意味着它在正確的單元格上執行,但我無法獲取文本以反映它是哪個單元格。我終於決定像下面那樣快速構建上下文菜單。它工作得很好,儘管看起來我應該能夠做得更好。

我打算給Erno答案並將其關閉。

private void OnCurrentCellChanged(object sender, EventArgs e) 
    { 
     if (ReferenceEquals(null, sender)) return; 
     var grid = (DataGrid)sender; 
     var selectedActivity = (ActivityViewModel)grid.CurrentItem; 
     if (ReferenceEquals(selectedActivity, null)) return; 

     if (_isEditableDayOfTheWeekColumn(grid.CurrentColumn)) 
     { 
      var dowCol = (DayOfTheWeekColumn)grid.CurrentColumn; 
      var index = Convert.ToInt32(dowCol.DowIndex); 
      selectedActivity.SetSelectedAllocationVm(index); 
     } 
     else 
     { 
      selectedActivity.SetSelectedAllocationVm(-1); 
     } 
     var commands = selectedActivity 
      .AllCommands 
      .Select(vmMenuItem => vmMenuItem.Command.ToMenuItem()); 
     var cm = new ContextMenu(); 
     foreach (var item in commands) 
     { 
      //item.SetResourceReference(StyleProperty, "ContextMenuItemStyle"); 
      cm.Items.Add(item); 
     } 
     grid.ContextMenu = cm; 
    } 

回答

1

我的猜測是你想要在代碼中使用Style。 只需創建Style類的一個實例,設置它的屬性(包括綁定)並將其添加到樹中的Resources屬性。

接下來,在生成的菜單項中使用樣式。

+0

@Erno。是有道理的,但我不能做得對。請看我最近的編輯;你能否抓取一些代碼?歡呼聲 – Berryl 2011-04-02 20:06:56

+0

@Erno。我的壞,我在ContextMenu而不是MenuItem上設置樣式。它看起來很正常,但仍然不更新 – Berryl 2011-04-02 20:19:44

+0

您是否意味着菜單項中的運行時更改爲樣式不可見?你不應該簡單地引用樣式(一種StaticResource),而是使用menuItem.SetResourceReference(StyleProperty,「ContextMenuItemStyle」); – 2011-04-02 21:05:07