3

我正在将 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;
    }
4

1 回答 1

1

我的猜测是您也想在代码中使用样式。只需创建 Style 类的实例,设置其属性(包括绑定)并将其添加到树中的 Resources 属性。

接下来,使用生成的菜单项中的样式。

于 2011-04-02T18:30:33.010 回答