Vi Ki
Vi Ki

Reputation: 43

Caliburn.Micro and ContextMenu for DataGrid Row

I have a ContextMenu in WPF DataGridRow.

<ContextMenu x:Key="RowContextMenu">
    <MenuItem cal:Message.Attach="SomeMethod()"/>
</ContextMenu>
<Style x:Key="RowWithContextMenu" TargetType="{x:Type DataGridRow}">
    <Setter Property="ContextMenu" Value="{StaticResource RowContextMenu}" />
</Style>

Each row in DataGrid represents an individual view-model class instance. Let's call it RowViewModel. When I click the menu item, SomeMethod() is executed and everything is OK for the first time, but clicking menu item on other rows executes SomeMethod() for the row where ContextMenu was shown for the first time.

I put some breakpoints in CM's ActionMessage.cs source code and found out that clicking the right mouse button to show menu for the first time invokes event calling ElementLoaded() method which in turn calls UpdateContext(). So context (it is RowViewModel) is created for menu item but it is never re-assigned when calling context menu on other rows.

Upvotes: 1

Views: 1546

Answers (1)

Ibrahim Najjar
Ibrahim Najjar

Reputation: 19423

You should take advantage of the bubbling feature of Action Messages to handle this more easily and elegantly.

Instead of putting SomeMethod() on each RowViewModel instance, you should put it on the DataContext of the DataGrid itself, then change SomeMethod() signature so i takes a RowViewModel as a parameter which is of course the DataContext of each row, so now it looks like this SomeMethod(RowViewModel rowViewModel) and then use cal:Message.Attach="SomeMethod($dataContext)" in XAML.

After that you should configure the ContextMenu so that it sends the action messages bubbling to it so that they reach the DataContext of the DataGrid but this this tricky and requires some looking around.

Look at this question and this to learn more about doing it.

Upvotes: 3

Related Questions