WPF prevent TreeViewItem to inherit contextMenu from parent by code - wpf

I have the following code and I set explicite the ContextMenu from a TreeViewItem to null but it shows all the time the same ContextMenu as the treeviewitem parents! Is that a bug? and how can I solve that?
Tree.Items.Clear();
System.Windows.Controls.TreeViewItem ceo = new System.Windows.Controls.TreeViewItem() { Header = "CEO" };
System.Windows.Controls.TreeViewItem manager1 = new System.Windows.Controls.TreeViewItem() { Header = "Manager1" };
System.Windows.Controls.TreeViewItem manager2 = new System.Windows.Controls.TreeViewItem() { Header = "Manager2" };
System.Windows.Controls.TreeViewItem person1 = new System.Windows.Controls.TreeViewItem() { Header = "person1" };
System.Windows.Controls.TreeViewItem person2 = new System.Windows.Controls.TreeViewItem() { Header = "person2" };
manager1.Items.Add(person1);
manager2.Items.Add(person2);
ceo.Items.Add(manager1);
ceo.Items.Add(manager2);
Tree.Items.Add(ceo);
// context Menu
MenuItem menu1 = new MenuItem();
menu1.Header = "Menu1";
MenuItem menu2 = new MenuItem();
menu2.Header = "Menu2";
MenuItem menu3 = new MenuItem();
menu3.Header = "Menu3";
MenuItem menu4 = new MenuItem();
menu4.Header = "Menu4";
MenuItem menu5 = new MenuItem();
menu5.Header = "Menu5";
MenuItem menu6 = new MenuItem();
menu6.Header = "Menu6";
System.Windows.Controls.ContextMenu ceoMenu = new ContextMenu();
ceoMenu.Items.Add(menu1);
ceoMenu.Items.Add(menu2);
ceoMenu.Items.Add(menu3);
System.Windows.Controls.ContextMenu managerMenu = new ContextMenu();
managerMenu.Items.Add(menu4);
managerMenu.Items.Add(menu5);
ceo.ContextMenu = ceoMenu;
manager1.ContextMenu = managerMenu;
manager2.ContextMenu = managerMenu;
System.Windows.Controls.ContextMenu personMenu = new ContextMenu();
personMenu.Items.Add(menu6);
person1.ContextMenu = personMenu;
person2.ContextMenu = null;

It works fine to set it like:
System.Windows.Controls.ContextMenu nullMenu = new ContextMenu();
nullMenu.Visibility = Visibility.Hidden;
person1.ContextMenu = personMenu;
person2.ContextMenu = nullMenu;

It's not a bug. If you set breakpoint on ContextMenuOpening event for person2, you will see, that it doesn't fired at all.
After that you can try to set breakpoint on ContextMenuOpening event for manager2. It's fired and on person2 node, but only because TreeViewItem is ItemsControl.
In WPF Visualizer we can see that:

It's not a bug. It is logical behavior. For example, if user clicks at the column at DataGrid, then it always shows the same ContextMenu. So if you set ContextMenu to null, then it just replaces your context menu by base context menu.
So we can make a little trick. We just change state of visibility of your ContextMenu.
So to have the personal Visibility of ContextMenu, you should just create another state of Visibility(Hidden, Visible or Collapse) to your created ContextMenu.
System.Windows.Controls.ContextMenu personMenu = new ContextMenu();
personMenu.Items.Add(menu6);
personMenu.Visibility = System.Windows.Visibility.Hidden;
person1TVI.ContextMenu = personMenu;
person2TVI.ContextMenu = personMenu;

Related

Custom ContextMenu for images in a RichTextBox

Users can embed images to a RichTextBox - I add them in an InlineUIContainer.
I've added a custom ContextMenu to the InlineUIContainer, but when right-clicked
the standard RTB-contextmenu (cut, copy, paste) appears - not the custom one.
Why, and how can I fix this?
string fileName = openFileDialog.FileName;
BitmapImage bitmap = new BitmapImage(new Uri(fileName, UriKind.Absolute));
Image image = new Image();
image.Source = bitmap;
image.Width = bitmap.Width;
image.Height = bitmap.Height;
InlineUIContainer pix = new InlineUIContainer(image, rt.CaretPosition);
pix.BaselineAlignment = BaselineAlignment.Center;
pix.ContextMenu = (ContextMenu)this.Resources["imageContext"];
Right, this works - I had to recreate the all the "standard" context menu items, including the spellchecking ones (fortunately I found an example of that : )
private void rt_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
int index = 0;
MenuItem menuItem;
this.rt.ContextMenu.Items.Clear(); //Clearing the existing items
// right clicked on an image ?
int offZstart, offZend;
activeImg = null;
foreach (Block block in rt.Document.Blocks)
{
Paragraph p = block as Paragraph;
if (p != null)
{
foreach (Inline inline in p.Inlines)
{
InlineUIContainer iuic = inline as InlineUIContainer;
if (iuic != null)
{
offZstart = rt.Selection.Start.GetOffsetToPosition(iuic.ContentStart);
offZend = rt.Selection.End.GetOffsetToPosition(iuic.ContentEnd);
// if (rt.Selection.Contains(iuic.ContentStart))
if ((offZstart == 2 || offZstart == 1) && (offZend == -2 || offZend == -1))
{
if (iuic.Child is Border) // I wrap my images in borders
{
Border border = (Border)iuic.Child;
activeImg = (Image)border.Child;
MenuItem imageMenu = new MenuItem();
imageMenu.Header = "Image..";
this.rt.ContextMenu.Items.Insert(index++, imageMenu);
MenuItem borderItem = new MenuItem();
borderItem.Header = "Border";
borderItem.Click += imgBorderWidth;
imageMenu.Items.Add(borderItem);
MenuItem marginItem = new MenuItem();
marginItem.Header = "Margin";
marginItem.Click += imgMarginWidth;
imageMenu.Items.Add(marginItem);
MenuItem paddingItem = new MenuItem();
paddingItem.Header = "Padding";
paddingItem.Click += imgPaddingWidth;
imageMenu.Items.Add(paddingItem);
}
}
}
}
}
}
// spellchecking
SpellingError spellingError = this.rt.GetSpellingError(this.rt.CaretPosition);
if (spellingError != null && spellingError.Suggestions.Count() >= 1)
{
//Creating the suggestions menu items.
foreach (string suggestion in spellingError.Suggestions)
{
menuItem = new MenuItem();
menuItem.Header = suggestion;
menuItem.FontWeight = FontWeights.Bold;
menuItem.Command = EditingCommands.CorrectSpellingError;
menuItem.CommandParameter = suggestion;
menuItem.CommandTarget = this.rt;
this.rt.ContextMenu.Items.Insert(index++, menuItem);
}
//Getting the word to add/ignore
var word = this.rt.GetSpellingErrorRange(this.rt.CaretPosition);
this.rt.ContextMenu.Items.Insert(index++, new Separator());
//Adding the IgnoreAll menu item
MenuItem IgnoreAllMenuItem = new MenuItem();
IgnoreAllMenuItem.Header = "Ignore All ''"+word.Text+"''";
IgnoreAllMenuItem.Command = EditingCommands.IgnoreSpellingError;
IgnoreAllMenuItem.CommandTarget = this.rt;
this.rt.ContextMenu.Items.Insert(index++, IgnoreAllMenuItem);
this.rt.ContextMenu.Items.Insert(index++, new Separator());
//Add as new word in dictionary
MenuItem AddToDictionary = new MenuItem();
AddToDictionary.Header = "Add ''" + word.Text + "'' to dictionary";
AddToDictionary.Command = EditingCommands.IgnoreSpellingError;
AddToDictionary.CommandTarget = this.rt;
AddToDictionary.Click += (object o, RoutedEventArgs rea) =>
{
//this.AddToDictionary(word.Text);
MessageBox.Show("Want to add ''" + word.Text + "'' to dictionary\n- but don't know how..");
};
this.rt.ContextMenu.Items.Insert(index++, AddToDictionary);
this.rt.ContextMenu.Items.Insert(index++, new Separator());
}
//Cut
MenuItem cutMenuItem = new MenuItem();
cutMenuItem.Command = ApplicationCommands.Cut;
this.rt.ContextMenu.Items.Insert(index++, cutMenuItem);
//Copy
MenuItem copyMenuItem = new MenuItem();
copyMenuItem.Command = ApplicationCommands.Copy;
this.rt.ContextMenu.Items.Insert(index++, copyMenuItem);
//Paste
MenuItem pasteMenuItem = new MenuItem();
pasteMenuItem.Command = ApplicationCommands.Paste;
this.rt.ContextMenu.Items.Insert(index++, pasteMenuItem);
this.rt.ContextMenu.Items.Insert(index++, new Separator());
//Delete
MenuItem deleteMenuItem = new MenuItem();
deleteMenuItem.Command = EditingCommands.Delete;
this.rt.ContextMenu.Items.Insert(index++, deleteMenuItem);
this.rt.ContextMenu.Items.Insert(index++, new Separator());
//Select All
MenuItem selectAllMenuItem = new MenuItem();
selectAllMenuItem.Command = ApplicationCommands.SelectAll;
this.rt.ContextMenu.Items.Insert(index++, selectAllMenuItem);
}

Change Lineseries thickness in WPFToolkit.Chart C#

I'm trying change the line thickness in a serie dinamically created, I need turn the line more thick.
Below, follow the code to bind the created serie on chart component. It works fine, but I tryed adapt this in this code and I had no sucess.
Please help, thanks.
Style style = new Style(typeof(LineDataPoint));
style.Setters.Add(new Setter(LineDataPoint.OpacityProperty, (double)(0.0)));
style.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, dadosSerie.ColorSerie));
LineSeries lineSerie = new LineSeries()
{
Title = dadosSerie.SerieTitle,
IndependentValueBinding = new Binding("Key"),
DependentValueBinding = new Binding("Value"),
DependentRangeAxis = dadosSerie.EixoY,
DataPointStyle = style,
ItemsSource = dadosSerie.DataSerie,
};
chtGraficos.Series.Add(lineSerie);
Have you tried adding a Style for the serie's Polyline instead?
It seams the style for the LineDataPoint is actually for every point on the serie.
Here is a working sample of a chart fully created on code-behind. You just have to create a window named MainWindow and add a reference on the project to System.Windows.Controls.DataVisualization.Toolkit:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var valueList = new Dictionary<string, int>();
valueList.Add("Developer", 60);
valueList.Add("Misc", 20);
valueList.Add("Project Manager", 40);
var style = new Style(typeof(Polyline));
style.Setters.Add(new Setter(Polyline.StrokeThicknessProperty, 10d));
var series = new LineSeries
{
PolylineStyle = style,
ItemsSource = valueList,
DependentValuePath = "Value",
IndependentValuePath = "Key",
};
var lineChart = new Chart { Height = 254 };
lineChart.Series.Add(series);
var mainGrid = new Grid();
mainGrid.Children.Add(lineChart);
this.Content = mainGrid;
}
}

Combobox binding not working when window is in grid container

I try to bind a list in ComboBox with this code :
var template = new DataTemplate();
var comboBoxFactory = new FrameworkElementFactory(typeof(ComboBox));
template.VisualTree = comboBoxFactory;
Binding b = new Binding();
b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, this.GetType(), 1);
b.Path = new PropertyPath("DataContext");
comboBoxFactory.SetBinding(ComboBox.ItemsSourceProperty, b);
comboBoxFactory.SetBinding(ComboBox.SelectedItemProperty, new Binding("ClassRoom"));
It's working when I launch the window simply, like this :
winListOrgane ee = new winListOrgane();
ee.Show();
But when I try to put this window in a grid container, it's not working :
_currentWindow = (ModelPage)Activator.CreateInstance(pPage.GetType());
_currentWindow.SetParam(genParam);
_currentWindow.InitPage();
object content = _currentWindow.Content;
_currentWindow.Content = null;
_containerPage.Children.Add((UIElement)content);
What can I do to fix this problem?
Thanks
Best regards,
Frederic
It looks like it is your RelativeSource on the Binding. Since you are binding to a specific Window class - in this case it looks like GetType() will return typeof(winListOrgane). If you change that to typeof(Window), it should work:
b.RelativeSource =
new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1);

WPF Binding a Dynamically Added Control

I am adding a to the "Company" RibbonApplicationMenuItem in my RibbonWindow with the following code:
var reset = DataContext as ICompanies;
if (reset != null)
{
// ToDo: Create interface to populate the mymenutems
var mymenuitems = new List<string>();
foreach (var item in mymenuitems)
{
var newbutton = new Button { Margin = new Thickness(2), Content = item };
MenuItem_Company.Items.Add(newbutton);
}
}
My XAML looks like this:
<ribbon:RibbonApplicationMenu ToolTipTitle="Application Menu">
<ribbon:RibbonApplicationMenuItem
Header="Company"
x:Name="MenuItem_Company"
ImageSource="Images\LargeIcon.png">
</ribbon:RibbonApplicationMenuItem>
</ribbon:RibbonApplicationMenu>
How do I bind my new button in code when I add it to the MenuItem_Company? I need it to bind to a property in my datacontext.
Thanks,
Eroc
var newbutton = new Button { Margin = new Thickness(2), Content = item };
Binding b = new Binding();
b.Source = reset;
b.Path = new PropertyPath("SomePropertyOnDataContext");
newButton.SetBinding(Button.IsEnabledProperty, b);
Varying assumptions in the code...but it should give you an idea where to start...

How do I create a Treeview with a Context Menu in Silverlight 4?

Silverlight 4 now include the option for creating a context menu upon right clicking. Can anyone provide me with an example of a treeview with a right click context menu for the treeview?
Ultimately I want a the menu to show different options depending upon the node depth selected - bonus points if the example includes this!
You can use this open source menu for this:
http://sl4popupmenu.codeplex.com
The control supports right click on TreeViews out of the box. The code has been adapted from the sample code on the homepage to use a TreeView instead of a DataGrid:
private void GenerateMenu()
{
var data = new ObservableCollection<string>("Item 1,Item 2,Item 3,Item 4,Item 6,Item 7,Item 8".Split(','));
TreeView treeView1 = new TreeView() { Margin = new Thickness(50), ItemsSource = data };
this.LayoutRoot.Children.Add(dataGrid1);
// Create the submenu
var pmTimeSub = new PopupMenu();
pmTimeSub.AddItem("Time Now", null);
// Create the main menu
var pm = new PopupMenu();
pm.AddItem("Delete row", delegate { data.RemoveAt(dataGrid1.SelectedIndex); });
pm.AddSeparator();
pm.AddSubMenu(pmTimeSub, "Get Time ", "images/arrow.png", null, null, false, null);
// Attach the submenu pmTimeSub
pm.AddSeparator();
pm.AddItem("Demo2", delegate { this.Content = new Demo2(); });
// Set dataGrid1 as the trigger element
pm.AddTrigger(TriggerTypes.RightClick, treeView1);
// Showing main menu
pm.Showing += (sender, e) =>
{
pm.PopupMenuItem(0).Header = "Delete " + treeView1.SelectedItem;
TreeViewItem tvi = pm.GetClickedElement<TreeViewItem>();
// Add code to calculate the node depth here using the GetParentTreeViewItem method
// Add code to modify the menu items according to the node depth value.
pm.PopupMenuItem(0).IsVisible =
pm.PopupMenuItem(1).IsVisible = tvi != null;
};
// Showing submenu
pmTimeSub.Showing += delegate
{
pmTimeSub.PopupMenuItem(0).Header = DateTime.Now.ToLongTimeString();
};
}
Note that the code does not allow you to show different menus upon the node depth yet. To do this you can use the following method to get the parent of the TreeViewItem that was clicked:
private static TreeViewItem GetParentTreeViewItem(DependencyObject item)
{
if (item != null)
{
DependencyObject parent = VisualTreeHelper.GetParent(item);
TreeViewItem parentTreeViewItem = parent as TreeViewItem;
return parentTreeViewItem ?? GetParentTreeViewItem(parent);
}
return null;
}
From there you can determine depth of the node by calling the GetParentTreeViewItem function in a loop until the parent is null. You would place this code in the event where the menu is being shown and then add the necessary code in there to show the appropriate menu.
Hope this helps.
So, I tried the above code, downloaded and attempted to include within my Existing Silverlight Application. I was able to find an easier solution. This will add a Context Menu allowing Right-Clicks on the Branches (Headers, or Parent Nodes).
private ContextMenu menu;
foreach(var model in models)
{
// Populate the Tree View Control
var cb = new CheckBox {Content = model.Value};
cb.Click += new RoutedEventHandler(cb_Click);
var header = new TreeViewItem {Header = cb};
// Menu for Header
menu = new ContextMenu();
MenuItem setAsRows = new MenuItem();
setAsRows.Header = "Set as Rows";
setAsRows.Click += new RoutedEventHandler(setAsRows_Click);
menu.Items.Add(setAsRows);
MenuItem addToRows = new MenuItem();
addToRows.Header = "Add to Rows";
addToRows.Click += new RoutedEventHandler(addToRows_Click);
menu.Items.Add(addToRows);
MenuItem setAsCols = new MenuItem();
setAsCols.Header = "Set as Columns";
menu.Items.Add(setAsCols);
MenuItem addToCols = new MenuItem();
addToCols.Header = "Add to Columns";
menu.Items.Add(addToCols);
header.ContextMenu = menu;
treeView1.Items.Add(header);
var thisItem = treeView1.Items;
// Model Contexts
var contexts = myFramework.GetConceptsOfModel(model.Key);
// Add Leafs To Branch
foreach(var context in contexts)
{
cb = new CheckBox {Content = context.Value.ToString()};
header.Items.Add(cb);
}
}

Resources