我正在将 xaml 中的三个相关但不同的 DataGrid 重构为代码,并遇到更新上下文菜单标题文本的问题。
命令和文本需要根据当前单元格是哪个数据网格单元格进行更新。标题文本在 xaml 中更新得很好,但如下图所示,它现在显示为空字符串。该命令本身可以正常工作,并且可以在正确的网格单元上工作。
标题文本触发属性的设置器已更改,但我怀疑我的代码没有像 xaml 等效项那样复制绑定。我也不确定 Shared 属性是否是我需要在代码中考虑的东西。
有谁知道我可以如何改进我正在使用的代码?
干杯,
贝里尔
建立绑定的 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>
代码
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;
}
更新
好吧,空字符串部分只是我自己的愚蠢 - 我没有初始化标题文本!下图是我现在得到的,算是改进了。文本应更新为星期几,即“使星期一成为一整天”
编辑 Erno
我正在为网格本身设置列和样式,如下所示,所以我想我可以获取上下文菜单的资源并进行设置。
然而,我得到了一个奇怪的结果,正如您从图片中看到的那样 - 就像上下文菜单覆盖了整个网格!
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");
}
}
最新更新
我试着按照这个 SO 帖子让我的绑定相对,但没有骰子。我的命令已更新,这意味着它在正确的单元格上执行,但我无法让文本反映它是哪个单元格。我终于决定动态构建上下文菜单,如下所示。它工作正常,虽然看起来我应该能够做得更好。
我将把答案交给 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;
}