I develop a Winforms app in C++/CLI. I added a MenuStrip object to my MDI Parent form. In the MenuStrip is a ToolStripMenuItem object, and to its DropDownItems collection is added a ToolStripMenuItem object everytime a new MDI Child form is created. I want to set the Checked property of a ToolStripMenuItem to true everytime it is clicked (and set it to false for all other ToolStripMenuItem instances). But there seems to be a problem displaying the check mark :
In the picture, the fourth item is supposed to be checked, but instead of displaying the check mark, all I see is a blue rectangle.
Here is the function in the MDI Parent form that creates a new canvas object (derived from System::Windows::Forms::Form class) :
void AddAndShowCanvas(ProjectID type, unsigned int index, System::String^ name, bool demo, bool data) {
m_Canvases->push_back(gcnew canvas(m_MainController, this, type, index, name, demo, data));
m_Canvases->back()->MdiParent = this;
m_menuStrip->AddCanvasToWindowsToolStrip(m_Canvases->back());
if (data)
m_Canvases->back()->GetMainPanel()->DisplayLoadedFile();
m_Canvases->back()->Show();
}
Here is the function in hydro_menustrip class (derived from System::Windows::Forms::MenuStrip class) that adds a ToolStripMenuItem to a ToolStripMenuItem (declared as m_windowsToolStripMenuItem) of the hydro_menustrip instance :
void hydro_menustrip::AddCanvasToWindowsToolStrip(canvas^ canvas) {
System::Windows::Forms::ToolStripMenuItem^ canvasItem =
gcnew System::Windows::Forms::ToolStripMenuItem(canvas->GetProjectTitle());
m_windowsToolStripMenuItem->DropDownItems->Add(canvasItem);
m_windowsToolStripMenuItem->DropDownItems[m_windowsToolStripMenuItem->DropDownItems->Count - 1]->PerformClick();
canvasItem->Click += canvas->OpenCanvasEvent;
}
And here is the DropDownItemClicked event added to the m_windowsToolStripMenuItem object :
void hydro_menustrip::windows_DropDownItemClicked(System::Object^ sender, ToolStripItemClickedEventArgs^ e) {
for each(ToolStripMenuItem^ item in m_windowsToolStripMenuItem->DropDownItems)
item->Checked = false;
safe_cast<ToolStripMenuItem^>(e->ClickedItem)->Checked = true;
}
Related
I am trying to call a method from a UserControl from a different UserControl. I am not able to trace the UserControl i am trying to call the method from to call the method.
I am trying to call the following method that is in AddDeal.xaml.cs
public void loadDealProducts()
{
InfoBox.Information("loadDealProducts called.", "testing");
}
I am tracing the AddDeal UserControl and trying to call the method loadDealProducts() in file AddDealProducts.xaml.cs using the following method
Window window = null;
if (sender is Window)
window = (Window)sender;
if (window == null)
window = Window.GetWindow(sender);
return window;
(window as AddDeal).loadDealProducts();
But window is returning null so i can't call the method loadDealProducts.
Instead of getting a Window using GetWindow, is there a way of getting the UserControl? I tried Window.GetUserControl and UserControl.GetUserControl but there is no such method.
sender is the DependencyObject from AddDeal.xaml.cs which i get when i click a button on AddDeal.xaml as following:
<Button Click="BtnAddProducts" CommandParameter="{Binding Path=ProductID}">Add Product</Button>
which calls the following:
private void BtnAddProducts(object sender, RoutedEventArgs e)
{
var button = (Button)sender as DependencyObject;
Window AddProductsDialog = new Window {
Title = "Add Products to Deal",
Content = new AddDealProduct(button, productID, false, 0)
};
AddProductsDialog.ShowDialog();
}
As you can see i am sending button which is a DependencyObject on AddDeal.xaml.cs/xaml
When it opens a new window AddDealProduct, it has AddDealProduct.xaml (UI file) and its .xaml.cs code-behind file. In this file i want to call a function from the calling UserControl(AddDeal).
Ok I solved it.
I am sending a DependencyObject sender that i get from Button Click event from source Window UserControl, to another UserControl class, as a parameter.
Then i use the sender object to resolve a UserControl and call a function in its class from a different UserControl class.
To call the function i do the following:
AddDealUserControl ownerx2 = FindVisualParent<AddDealUserControl>(sender);
ownerx2.loadDealProducts();
FindVisualParent helper class:
public static T FindVisualParent<T>(DependencyObject child)
where T : DependencyObject
{
// get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
// we’ve reached the end of the tree
if (parentObject == null) return null;
// check if the parent matches the type we’re looking for
T parent = parentObject as T;
if (parent != null)
{
return parent;
}
else
{
// use recursion to proceed with next level
return FindVisualParent<T>(parentObject);
}
}
Hope it helps.
Given the following insane setup (a ComboBox inside a UserControl inside a ToolStripControlHost inside a ContextMenuStrip):
there's something odd going on with clicking on different items in the ComboBox popup. If the item is inside the menu bounds (i.e. Amsterdam, Brussel or Luxemburg) the item is selected. If the item is outside the menu bounds (i.e. Berlijn and further) the menu is closed immediately.
Ignoring any spiffy remarks regarding the sheer crazy, anyone know what's going on and how to stop the menu from closing if a distant combobox item is selected?
The problem is due to a check deep in the ToolStripManager determining the mouse event is not on a child.
Basically you need to reject the ContextMenuStrip.OnClosing event if the ComboBox is displaying. There's inevitably a cleaner solution but I didn't see one.
public bool IsDropDownShowing { get; private set; }
private void InitializeContextMenu()
{
var userControl = new ComboMenuUserControl();
var toolStripHost = new ToolStripControlHost(userControl);
contextMenuStrip1.Items.Add(toolStripHost);
userControl.comboBox1.DropDown += (o, args) => IsDropDownShowing = true;
userControl.comboBox1.DropDownClosed += (o, args) => IsDropDownShowing = false;
contextMenuStrip1.Closing += (o, args) =>
{
if (IsDropDownShowing == true)
args.Cancel = true;
};
}
When the user tabs into a CheckBox to give it focus, a dotted border appears around the CheckBox to indicate that it has focus.
When the CheckBox gets focused by code calling myCheckBox.Focus(), no such indicator appears (even though pressing the space bar toggles the state).
How can I make the CheckBox focus border appear when I have programmatically focused the CheckBox?
The border is intentionally only shown if you are navigating by the keyboard (Tab key). The MSDN page on this topic has further details:
Focus visual styles act only when the
focus action was initiated by the
keyboard. Any mouse action or
programmatic focus change disables the
mode for focus visual styles.
If you want to show a border, you could use a Trigger on the IsFocused- Property to do some visual changes (although you can't set the border with this) or if you actually want a border, you would have to create your own ControlTemplate.
There is also a thread here on SO on a somewhat related topic where the suggestion is to simulate a key press, but I would suggest not to use this solution for your problem.
By editing the KeyboardNavigationEx file from ControlzEx I managed to solve the issue (full credit goes, as always, to punker76).
Just call the KeyboardHelper.Focus method passing the UIElement that shoud be focused (e.g. KeyboardHelper.Focus(myCheckBox))
Here's the KeyboardHelper class:
public sealed class KeyboardHelper
{
private static KeyboardHelper _Instance;
private readonly PropertyInfo _AlwaysShowFocusVisual;
private readonly MethodInfo _ShowFocusVisual;
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static KeyboardHelper()
{
}
private KeyboardHelper()
{
var type = typeof(KeyboardNavigation);
_AlwaysShowFocusVisual = type.GetProperty("AlwaysShowFocusVisual", BindingFlags.NonPublic | BindingFlags.Static);
_ShowFocusVisual = type.GetMethod("ShowFocusVisual", BindingFlags.NonPublic | BindingFlags.Static);
}
internal static KeyboardHelper Instance => _Instance ?? (_Instance = new KeyboardHelper());
internal void ShowFocusVisualInternal()
{
_ShowFocusVisual.Invoke(null, null);
}
internal bool AlwaysShowFocusVisualInternal
{
get { return (bool)_AlwaysShowFocusVisual.GetValue(null, null); }
set { _AlwaysShowFocusVisual.SetValue(null, value, null); }
}
public static void Focus(UIElement element)
{
element?.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
var keybHack = KeyboardHelper.Instance;
var oldValue = keybHack.AlwaysShowFocusVisualInternal;
keybHack.AlwaysShowFocusVisualInternal = true;
try
{
Keyboard.Focus(element);
keybHack.ShowFocusVisualInternal();
}
finally
{
keybHack.AlwaysShowFocusVisualInternal = oldValue;
}
}));
}
}
'initially set chkCheckBox.Appearance = 1
'on Got Focus set appearance = 0 - Flat
Private Sub chkCheckBox_GotFocus()
chkCheckBox.Appearance = 0
End Sub
'on Lost Focus set appearance = 1 - 3D
Private Sub chkCheckBox_LostFocus()
chkCheckBox.Appearance = 1
End Sub
I have a Window with seven buttons; I use it as a menu in a simple game I am working on, but I display it as a dialog. How can I know which button user has pressed, since DialogResult in WPF only offers true, false and null?
If you're making a custom Window in this way, you don't really need to worry about DialogResult.
You can keep track of this in a property within your Window, and just read the property after the dialog is closed.
MyDialog window = new MyDialog();
if (window.ShowDialog() == false)
{
// user closed the window...
}
var choice = window.CustomPropertyContainingChoice;
Define your own enum and offer a static method to display the window that return your enum.
The code below does the same thing it is part of a window that allows users to review their changes and accept or cancel. As I only need true and false I used a bool however it would be trivial to change to an enum.
public static bool DisplayChanges(List<INormalizedMessage> LstMessages)
{
var retlist = LstMessages.Where(( INormalizedMessage NM ) => { return NM.Status != NormalizedMessageStatus.NoChange; });
ReviewChanges RC = new ReviewChanges();
RC.Messages = retlist.ToList();
RC.ShowDialog();
return RC.Result;
}
private void cmdCancle_Click( object sender, RoutedEventArgs e )
{
Result = false;
Hide();
}
private void cmdOK_Click( object sender, RoutedEventArgs e )
{
Result = true;
Hide();
}
I have a Menu and Submenu structure in Silverlight, and I want the submenu to disappear when the parent menu item loses focus - standard Menu behavior. I've noticed that the submenu's click events are lost when a submenu item is clicked, because the parent menu item loses focus and the submenu disappears.
It's easier to explain with code:
ParentMenuBtn.Click += delegate
{
SubMenu.Visibility = (SubMenu.Visibility == Visibility.Visible) ? SubMenu.Collapsed : SubMenu.Visible;
};
ParentMenuBtn.LostFocus += delegate
{
SubMenu.Visibility = Visibility.Collapsed;
};
SubMenuBtn.Click += delegate
{
throw new Exception("This will never be thrown.");
};
In my example, when SubMenuBtn is clicked, the first event that triggers is ParentMenuBtn.LostFocus(), which hides the container of SubMenuBtn. Once the container's visibility collapses, the Click event is never triggered.
I'd rather avoid having to hide the sub-menu each time, but I'm a little surprised that the Click event is never triggered as a result...
I can't put any checks inside the LostFocus() event to see if my SubMenuBtn has focus, because it does not gain focus until after the LostFocus() event is called. In other words, SubMenuBtn.IsFocused = false when LostFocus() is triggered.
Anyone have any thoughts about this?
I've found out the solution - albeit, it's not as simple, or elegant as I would have liked. The solution is to use a secondary thread that pauses only for a moment before executing.
ie.
public partial class Navigation : UserControl
{
public Navigation()
{
ParentMenuBtn.Click += delegate
{
SubMenu.Visibility = (SubMenu.Visibility == Visibility.Visible) ? Visibility.Collapsed : Visibility.Visible;
};
ParentMenuBtn.LostFocus += delegate(object sender, RoutedEventArgs e)
{
HideSubMenu(SubMenu);
};
SubMenuBtn.Click += delegate
{
//Sub Menu Button actions...
};
private void HideSubMenu(UIElement subMenu)
{
//Get the Main Page
App app = (App)Application.Current;
MainPage mainPage = (MainPage)app.RootVisual;
Thread thread = new Thread(Navigation.HideSubMenu);
thread.Start(new ThreadState(mainPage, subMenu));
}
private static void HideSubMenu(object threadStateObj)
{
ThreadState threadState = (ThreadState)threadStateObj;
//Execute after 5 milliseconds...
System.Threading.Thread.Sleep(5);
threadState.MainPage.Dispatcher.BeginInvoke(delegate() {
threadState.TargetElement.Visibility = Visibility.Collapsed;
});
}
I just use a simple object called ThreadState to handle all the state objects I want to preserve:
public class ThreadState
{
public MainPage MainPage = null;
public UIElement TargetElement = null;
public ThreadState(MainPage mainPage, UIElement targetElement)
{
this.MainPage = mainPage;
this.TargetElement = targetElement;
}
}