This is a migrated thread and some comments may be shown as answers.

How to bind RadMenuItem to a command of parent model and pass current item to parameter?

3 Answers 1053 Views
ListBox
This is a migrated thread and some comments may be shown as answers.
Bill
Top achievements
Rank 1
Bill asked on 22 Jan 2020, 10:20 PM

Hi, 

I have some struggle with context menu binding. The problem is that I cant bind Command from  CustomerViewModel  to a RadMenuItem in a Context menu.

Here is my code:

public class CustomerViewModel : ViewModelBase
{
    private ObservableCollection<Customer> _customers;
 
    public ICommand AddCom { get; set; }
    public ICommand DelCom { get; set; }
    public CustomerViewModel()
    {
        AddCom = new DelegateCommand(Add);
        DelCom = new DelegateCommand(Del);
    }
 
    private void Add(object o)
    {
        Customers.Add(new Customer(){Id=Customers.Count,
                Name="Customer "+ Customers.Count.ToString()} );
        OnPropertyChanged(() => this.Customers);
    }
    private void Del(object o)
    {
        Customers.Remove((Customer) o);
        OnPropertyChanged(() => this.Customers);
    }
     
    public ObservableCollection<Customer> Customers
    {
        get => this._customers;
        set
        {
            if (this._customers == value) return;
            this._customers = value;
            this.OnPropertyChanged(() => this.Customers);
        }
    }
}

and XAML

<Window x:Class="CustomListBoxDragDropBehavior.MainWindow"
        xmlns:local="clr-namespace:CustomListBoxDragDropBehavior"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" >
    <d:Window.DataContext>
        <local:CustomerViewModel/>
    </d:Window.DataContext>
    <Window.Resources>
        <telerik:RadContextMenu x:Key="Menu">
            <telerik:RadMenuItem Header="Add customer" Command="{Binding ??? }" />
            <telerik:RadMenuItem Header="Remove customer" Command="{Binding ???}"
                   CommandParameter=" ??? "/>/>
        </telerik:RadContextMenu>
        <Style x:Key="ListBoxItem" TargetType="telerik:RadListBoxItem">
            <Setter Property="telerik:RadContextMenu.ContextMenu" Value="{StaticResource Menu}"/>
        </Style>
    </Window.Resources>
 
    <Grid >
        <telerik:RadListBox ItemContainerStyle="{StaticResource ListBoxItem}"
                            ItemsSource="{Binding Customers, Mode=TwoWay}"
                            DisplayMemberPath="Name"
                            >
        </telerik:RadListBox>
    </Grid>
</Window>

I tried few combination like 

<telerik:RadMenuItem Header="Item" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.AddCom }" />

with no success. Also I need to pass current customer to a DelCom as parameter.

Please advise.

 

3 Answers, 1 is accepted

Sort by
0
Bill
Top achievements
Rank 1
answered on 23 Jan 2020, 04:11 PM

I found if in my previous example change RadContextMenu to standard ContextMenu everything starts work perfectly, including command binding and command parameters passing.

<ContextMenu x:Key="Menu">
    <MenuItem Header="Item" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.AddCom }" />
   <MenuItem Header="Item2" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.DelCom }"
          CommandParameter="{Binding }"/>
</ContextMenu>
<Style x:Key="ListBoxItem" TargetType="telerik:RadListBoxItem">
   <Setter Property="ContextMenu.ContextMenu" Value="{StaticResource Menu}"/>
</Style>

 

But when I substituted ContextMenu to RadContextMenu it all bindings looked broken. Context menu appears but  not call the commands.

Is it a bug in a RadContextMenu or it should have different bindings format?

 

0
Vladimir Stoyanov
Telerik team
answered on 27 Jan 2020, 02:00 PM

Hello Bill,

Thank you for the provided code snippets.

Can you check out the First Look RadContextMenu example from our demos? It demonstrates how to set the RadContextMenu on a ListBox, bind to commands from the viewmodel and also pass in the clicked item as the CommandParameter. 

I hope you find this helpful.

Regards,
Vladimir Stoyanov
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
fabrizio
Top achievements
Rank 1
Iron
answered on 03 Mar 2025, 09:34 AM | edited on 03 Mar 2025, 09:37 AM

Hello, 

I am having a similar issue while trying to bind my RadMenuItem to the data-context of a relative source of type of the containing user control.

For weird reasons, it seems like it does not inherit correctly the parent data-context and the binded value always results in a binding error.

I have tried playing with "InheritDataContext" property, too, without success.

My RadMenuItem is within a row of RadGridView if it can help. Despite that, everything should work as usual without weird behaviours.

 

Can you help on this?

 

Regards,

Fabrizio

 

Stenly
Telerik team
commented on 04 Mar 2025, 11:24 AM

Hello Fabrizio,

I prepared a sample project where the RadContextMenu control is defined on the row-level of the RadGridView and the items of it execute a command from the main view model of the view. This is done via the suggestion provided by my colleague, Vladimir, in the above answer. The ExtendedContextMenu class from our Demos application is modified a bit to work with the GridViewRow element rather than the ListBoxItem one.

Could you give the attached project a try and let me know how it goes?

fabrizio
Top achievements
Rank 1
Iron
commented on 04 Mar 2025, 03:37 PM | edited

Hello Stenly,

thank you for your example.

Tried to use it and got the following binding error

"""

BindingExpression path error: 'ClickedGridViewRowItem' property not found on 'object' ''RadContextMenu' (Name='')'. BindingExpression:Path=Menu.ClickedGridViewRowItem.GridViewDataControl.DataContext.DataQualityMoveCommand; DataItem='RadMenuItem' (Name=''); target element is 'RadMenuItem' (Name=''); target property is 'Command' (type 'ICommand')

"""

As you guessed, the Command is in the main view model of the view.

If it can be of help instead, my RadContextMenu is the content of a button within a CellTemplate of RadGridView.

 

Thank you,

Fabrizio

Vladimir Stoyanov
Telerik team
commented on 06 Mar 2025, 09:24 AM

Hello Fabrizio,

I updated the sample project shared by my colleague based on the additional information, however I was not able to reproduce the described binding error. 

May I ask you to check out the updated project and see how it differs from the setup on your end? Should you need any further assistance, you can update the sample project in order to demonstrate your scenario and send it back. This will hopefully allow me to investigate further and provide further suggestions. 

I am looking forward to your reply.

fabrizio
Top achievements
Rank 1
Iron
commented on 02 Apr 2025, 02:24 PM

Hello Vladimir,

I tried your implementation and worked correctly for a while until the team noticed a weird behaviour.

My current UI:

Basically, as said, the extended context-menu is shown when the user clicks on a button within a CellTemplate of a grid.

When the user clicks on a row of the same grid instead, we have binded another command that resizes the grid (and show something else on the side)

Bug:

it happens that if the users opens the ExtendedContextMenu and then clicks on another row while the menu is still visibile, an unhandled exception is thrown by Telerik internals.

Note: this bug weirdly does not occur with the classic version of the ContextMenu.

Stack:

NullReferenceException
at Telerik.Windows.Controls.Primitives.SharedSizeContentPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV) at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged) at System.Windows.Controls.Grid.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Grid.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Control.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.StackPanel.StackMeasureHelper(IStackMeasure measureElement, IStackMeasureScrollData scrollData, Size constraint) at System.Windows.Controls.StackPanel.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) at System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Grid.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) at System.Windows.Controls.ScrollContentPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Grid.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.ScrollViewer.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Grid.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Border.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Grid.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Grid.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Control.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.ContextLayoutManager.UpdateLayout() at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg) at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks() at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget) at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Conclusion:

fabrizio
Top achievements
Rank 1
Iron
commented on 02 Apr 2025, 02:25 PM

my comment was cut.

The conclusion was:

I am very surpised by this weird behaviour. Do you have any clue?

Vladimir Stoyanov
Telerik team
commented on 03 Apr 2025, 09:40 AM

Hello Fabrizio,

I went over the shared stacktrace, however it is difficult to suggest anything without being able to reproduce the error on my end. I updated the sample project to better resemble the scenario that you described, however I was not able to replicate the same behavior. That is why I am attaching the updated sample project that I used for testing.

Can you modify the sample project in order to demonstrate the observed on your end behavior? Alternatively, you can also send over a sample project of your own. This will help me to provide suggestions specific for your scenario. 

Thank you in advance for any help you can provide.

fabrizio
Top achievements
Rank 1
Iron
commented on 22 Apr 2025, 02:33 PM

Hello Vladimir,

I managed to understand the root-cause of the issue.

When a new row was clicked I was collapsing the button of the previously selected one - causing unhandled behaviours on the rendering side that I didn't have time to deep-dive into.

I fixed it by hiding the button instead of collapsing it.

 

Thank you for your support,

Fabrizio

Vladimir Stoyanov
Telerik team
commented on 23 Apr 2025, 07:51 AM

Hello Fabrizio, 

I am glad to hear that you were able to achieve the desired requirement. Thank you for sharing your findings. 

Of course, feel free to contact us again, if you have any other questions. 

Tags
ListBox
Asked by
Bill
Top achievements
Rank 1
Answers by
Bill
Top achievements
Rank 1
Vladimir Stoyanov
Telerik team
fabrizio
Top achievements
Rank 1
Iron
Share this question
or