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

Changing column visibility in a context menu

10 Answers 764 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Chris Ryder
Top achievements
Rank 1
Chris Ryder asked on 29 Jun 2010, 06:01 PM
Hi,

I'm trying to display a standard context menu on a RadGridView that lists the columns that are contained within the grid.  The purpose of this is so that I can have a checkbox on the menu item that controls/changes the visibility of the column on the grid.  I've seen the article (http://www.telerik.com/help/wpf/radgridview-how-to-show-hide-columns-outside-of-the-radgridview.html) that shows how to dynamically populate a listbox with checkboxes using XAML and bindings - this is close to what I want.

I've tried to add the context menu directly to the RadGridView using the following XAML but had no luck so far:

<telerik:RadGridView HorizontalAlignment="Left" Margin="15" Name="radGridView1" VerticalAlignment="Top" AutoGenerateColumns="False"
                                 ItemsSource="{Binding ElementName=TheContext, Path=TestModels}">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn Header="AA" DataMemberBinding="{Binding Path=AA}" />
                    <telerik:GridViewDataColumn Header="BB" DataMemberBinding="{Binding Path=BB}" />
                </telerik:RadGridView.Columns>
                <telerik:RadGridView.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Columns" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=telerik:RadGridView, AncestorLevel=1}, Path=Columns, Mode=TwoWay}">
                            <MenuItem.ItemTemplate>
                                <HierarchicalDataTemplate>
                                    <MenuItem Header="Binding Header, Mode=TwoWay}" IsCheckable="True" IsChecked="{Binding IsVisible, Mode=TwoWay}"/>
                                </HierarchicalDataTemplate>
                            </MenuItem.ItemTemplate>
                        </MenuItem>
                    </ContextMenu>
                </telerik:RadGridView.ContextMenu>
            </telerik:RadGridView>

In the Output window I can see I get the following error message: System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Telerik.Windows.Controls.RadGridView', AncestorLevel='1''. BindingExpression:Path=Columns; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')

I thought perhaps I should try creating a context menu on something other than the RadGridView I've tried adding a context menu to a label that's outside of the RadGridView just to test things out but so far have called no joy.  The XAML I was using for this was:

<Label>
                <Label.Content>I'm a label but right click me...</Label.Content>
                <Label.ContextMenu>
                    <ContextMenu Name="MainCollection">
                        <MenuItem Header="Columns">
                            <MenuItem ItemsSource="{Binding ElementName=radGridView1, Path=Columns, Mode=TwoWay}">
                                <MenuItem.ItemTemplate>
                                    <HierarchicalDataTemplate>
                                        <MenuItem Header="Binding Header, Mode=TwoWay}" IsCheckable="True" IsChecked="{Binding IsVisible, Mode=TwoWay}"/>
                                    </HierarchicalDataTemplate>
                                </MenuItem.ItemTemplate>
                            </MenuItem>
                        </MenuItem>
                    </ContextMenu>
                </Label.ContextMenu>
            </Label>

From the output window I get the following error message "System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=radGridView1'. BindingExpression:Path=Columns; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')"

Any ideas welcome,
Chris.

10 Answers, 1 is accepted

Sort by
0
Yavor Georgiev
Telerik team
answered on 30 Jun 2010, 12:24 PM
Hello Chris Ryder,

 Because the context menu system in WPF uses Popup to display itself, it does not quite share the same airspace with the rest of the controls in the window. You can verify this behavior by setting a breakpoint when the context menu is displayed and invoking the WPF Tree Visualizer debug tool within Visual Studio.

The solution is to handle the context menu's Opened event and set its ItemsSource manually. I'm attaching a sample solution that shows how this is done with a RadContextMenu.

All the best,
Yavor Georgiev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Chris Ryder
Top achievements
Rank 1
answered on 30 Jun 2010, 03:45 PM

Hi Yavor,

Thank you for your reply - it's a shame it can't all be handled in XAML.

Thanks for the tip & explanation,
Chris.

0
Charlie M.
Top achievements
Rank 1
answered on 13 Oct 2010, 09:26 PM
If possible, I would like to extend this question. Using the same situation that Chris started with, being able to create a context menu on the fly using the example given with the GridView, how would you do the same thing with column headers that are just an image. I keep running into a problem using the sample code in which I get an error of :

Specified element is alread the logical child of another element. Disconnect it first.

After some work, I was able to adjust the example code as follows:

Style sytelColHeader =
new Style()
Setter setterIsCheckable =
new Setter {Property = RadMenuItem.IsCheckableProperty, Value = true };
Setter setterIsChecked =
new Setter();
Setter setterHeader =
new Setter();

Binding isCheckedBinding =
new Binding("IsVisible");
isCheckedBinding.Mode = BindingMode.TwoWay;

Binding columHeader =
new Binding("Header");
columHeader.Mode = BindingMode.TwoWay;

setterHeader.Property = radMenutItem.HeaderProperty;
setterHeader.Value = columnHeader;

setterIsChecked.Property = RadMenuItem.isCheckedProperty;
setterIsChecked.Value = isCheckedBinding;

styleColumnHeaderMenu.Setters.Add(setterIsChecked);
styleColumnHeaderMenu.Setters.Add(setterIsCheckable);
styleColumnHeaderMenu.Setters.Add(setterHeader);

radMenuItem item =
new RadMenuItem();
item.Header =
"Choose Columns:";
item.ItemsSource = grid.Columns;
item.itemsContainerStyle = styleColumnHeaderMenu;
menu.Items.Add(item);


Since my grid has image columns defined, as well as the somewhat working modification I have above, things are tied together between the context menu and the grid. Any suggestions would be great.
0
Yavor Georgiev
Telerik team
answered on 14 Oct 2010, 02:08 PM
Hello Charlie M.,

 If you're placing an Image in the column header, it's not possible to display it in the context menu as well, because a UI element cannot exist in two places simultaneously. You will have to somehow create two images and bind them to the same source or something along those lines.

Kind regards,
Yavor Georgiev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Charlie M.
Top achievements
Rank 1
answered on 15 Oct 2010, 10:18 PM
Thank you for the update.

For anyone else interested, to solve our problem, we ended up creating a copy of the image found in the HeaderCell and applied that to our submenu. Then used the rest of the code found in the example to bind to the column visibility.
0
Ivan
Top achievements
Rank 1
answered on 24 Jan 2014, 12:33 PM
Hello Yavor,

is it possible to remove/set invisible one or some 'ContextMenu-Item' after binding the columns of RadGridView?

I have tried that code, got exception.

private void RadContextMenu_Opened(object sender, RoutedEventArgs e)
{
  var menu = sender as RadContextMenu;
  menu.Items.RemoveAt(0);
}
Operation is not valid while using the "ItemsSource". Instead, use "ItemsControl.ItemsSource" to access elements and to change it.

Any idea? Thanks

Ivan
0
Yoan
Telerik team
answered on 29 Jan 2014, 03:04 PM
Hello Ivan,

You can achieve the desired result by using the ItemContainerStyleSelector of RadContextMenu. I have prepared a sample project which demonstrates the approach.


Regards,
Yoan
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Ivan
Top achievements
Rank 1
answered on 29 Jan 2014, 05:06 PM
Hello Yoan,

thanks for your answer. I have not seen your project. Is that being preparing, or have you forget to attach ;)

Regards,
Ivan
0
Yoan
Telerik team
answered on 30 Jan 2014, 09:38 AM
Hello Ivan,

I have attached the sample project again.

Regards,
Yoan
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Ivan
Top achievements
Rank 1
answered on 10 Feb 2014, 10:53 AM

Hello Yoan,

thanks a lot. That helps me.

Regards,
Ivan

Tags
GridView
Asked by
Chris Ryder
Top achievements
Rank 1
Answers by
Yavor Georgiev
Telerik team
Chris Ryder
Top achievements
Rank 1
Charlie M.
Top achievements
Rank 1
Ivan
Top achievements
Rank 1
Yoan
Telerik team
Share this question
or