создание контекстного меню в коде - PullRequest
3 голосов
/ 02 апреля 2011

Я перевожу три связанных, но разных DataGrids из xaml в код и решаю проблему с обновлением текста заголовка контекстного меню.

Команда и текст должны обновляться в соответствии с тем, какая ячейка сетки данных является текущей ячейкой.Текст заголовка обновлен в xaml, но, как видно из рисунка ниже, теперь он отображается в виде пустой строки.Сама команда работает правильно и работает с правильной ячейкой сетки.

Установщик свойства пожара текста заголовка изменился, но я подозреваю, что мой код не реплицирует привязку, как это делает эквивалент xaml.Я также не уверен, является ли атрибут Shared тем, что мне нужно учитывать в коде.

Кто-нибудь видит, как я могу улучшить код, который использую?

Cheers,
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>

КОД

    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;
    }

ОБНОВЛЕНИЕ

Ну пустая строкачасть была просто моей собственной глупостью - я не инициализировал текст заголовка!Изображение ниже - то, что я получаю сейчас, и это улучшение.Текст должен обновиться, чтобы указать день недели, т. Е. «Сделать понедельник полным днем» enter image description here

РЕДАКТИРОВАТЬ для Erno

Я устанавливаю столбцы и стиль для сеткиСамо по себе, как показано ниже, поэтому я подумал, что могу просто извлечь ресурс для контекстного меню и установить его.

Однако я получаю странный результат, как вы можете видеть на картинке - это похоже на то, что контекстное меню охватывает всю сетку!

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");
        }
    }

Последнее обновление

Я попытался установить относительную привязку для этого поста , но без кубиков.Моя команда обновлена, что означает, что она выполнена в правильной ячейке, но я не смог получить текст, который бы отражал, в какой ячейке она находилась.Я, наконец, просто решил создать контекстное меню на лету, как показано ниже.Это работает нормально, хотя, кажется, мне следовало бы добиться большего успеха.

Я собираюсь дать ответ Эрно и закрыть его.

    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 Ответ

1 голос
/ 02 апреля 2011

Полагаю, вы также хотите использовать стиль в коде. Просто создайте экземпляр класса Style, установите его свойства (включая привязку) и добавьте его к свойству Resources в дереве.

Далее используйте стиль в сгенерированных пунктах меню.

...