How to determine the active control within a tabControl - c#

I have a tab control through which the user can right-click within one of several richTextBoxes. The textBoxes use the same contextMenuStrip control, and I need to determine which textBox is the active one within the contextMenuStripCopyPaste_Opening event. I would think that the code to determine this would be
tabControl1.SelectedTab.ActiveControl.Name but the ActiveControl property is not available. this.ActiveControl.Name just gives me the name of the tabControl.
How can I determine which textBox is the active control within the tabControl?

You can use the sender paramter to get the ContextMenuStrip then call the ContextMenuStrip.SourceControl property to get the control that opened the context menu.
In this case you can try the following code.
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
var ctxStrip = sender as ContextMenuStrip;
if (ctxStrip == null)
return;
var rtb = ctxStrip.SourceControl as RichTextBox;
if (rtb == null)
return;
}
This code simply casts the sender object to a ContextMenuStrip if this is null then return. (Although should never be). The next line captures the SourceControl and casts the control to a RichTextBox.
If the source control is not a RichTextBox then the result will be null and we cancel as this shouldn't be null unless you bind the context menu to other controls aswell.

I'm not finding anything that is there by default. I would create a list of the rich text boxes, and then use a LINQ statement as the LINQ Select statement would return only the rich text box that has the focus. Something like this.
List rtbList = new List {RichTextBox1, RichTextBox2, RichTextBox3, RichTextBox4}
var FocusedRTB = rtbList.Select(x => x.Focused == true);
switch (FocusedRTB.Name)
{Execute Code for each RichTextBox
}

Related

How Can I Use a Semi-Dynamically Created Control Name?

I'm creating a new tab on a TabControl, and inside of that tab contains a RichTextBox semi-dynamically named by setting the name Variable like so:
chatWindow.Name = name + "ChatArea";
"name" being the name of the chat channel the user has joined.
ex: name = Test, RTB Name would be: TestChatArea.
Is there an easy way to access that control via code, or am I going about this the completely wrong way?
To programmatically retrieve the TabPage where your RichTextBox control is contained you should search all the tabPage inside your TabControl and check if any RichTextBox in that page has the Name that you are searching for
foreach(TabPage tp in yourTablControl.TabPages)
{
RichTextBox rtb = tp.Controls.OfType<RichTextBox().FirstOrDefault(x => x.Name == name + "ChatArea");
if(rtb != null)
{
// rtb is your control, do your stuff in a sub
// passing the found control and break the loop
DoYouStuffWithRichTextBox(rtb)
break;
}
}
Of course you need to have a way to identify the variable part of this code. Meaning the variable name should have been set before entering this loop with the actual value that you are searching for.
This code will be simpler if we can assume that you have just one RichTextBox for each TabPage. In this case, when dinamically creating the TabPage and its RichTextBox you could set the Name property of the TabPage to your chat area and use that as a way to identify your control
TabPage tp = yourTablControl.TabPages["chatAreaName"];
RichTextBox rtb = tp.Controls.OfType<RichTextBox().FirstOrDefault();
if(rtb != null)
{
....

Close a popup from an internal button - WPF

I have a ComboBox in a WPF application which contains a list and 'OK' button. I would like the ComboBox popup area to be closed when a user click on the OK button which in the ComboBox.
(I want the click event to change the property: IsDropDownOpen of the ComboBox
How can I cause an internal content to close its container?
You could try replacing the Button with a ToggleButton and bind the ToggleButton.IsChecked property to the ComboBox.IsDropDownOpen property using and 'inverse bool Converter' (a Converter class that returns the opposite of the bool input value.)
The only problem with this is that you would need to 'un-toggle' the ToggleButton each time the ComboBox drop down opened.
You could use the Logical/Visual Tree to get the containing ComboBox:
DependencyObject prop = sender as DependencyObject;
while (prop != null && !(prop is ComboBox))
{
prop = LogicalTreeHelper.GetParent(prop);
}
if (prop != null)
{
((ComboBox) prop).IsDropDownOpen = false;
}
Of course thats just a quick and dirty solution and should be cleaned up. ;)

Setting ToolStripMenuItem.Visible to true doesn't work

I have a TreeView control for which each node in it I want to share a ContextMenuStrip which has two ToolStripMenuItems ie:
this.BuildTree = new MyApp.MainForm.TreeView();
this.ItemMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowLogMenuItem = new System.Windows.Forms.ToolStripMenuItem();
...
this.ItemMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteMenuItem,
this.ShowLogMenuItem});
So I show and hide these to items according to certain criteria on a right click in a MouseUp event. When both are hidden I hide the ContextMenuStrip itself. Problem is when I hide the ContextMenuStrip it seems the next time I want to show one of the menu items I have to click twice on the node. The strange thing is on the first click to reshow one or both of the the items I have the following code:
ItemMenuStrip.Visible = true;
ShowLogMenuItem.Visible = true;
The two lines above don't seem to do anything ie both remain false in the debugger view after stepping over each line.
I don't think I've got any events on these values being set at least I don't have any events attached.
What am I doing wrong?
I suggest you to set:
this.BuildTree.ContextMenuStrip = this.ItemMenuStrip;
to make the menu automatically open on tree right-click.
Then subscribe ItemMenuStrip.Opening event to change the visibility of items and the contextmenu itself:
void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
if (something)
{
e.Cancel = true; // don't show the menu
}
else
{
// show/hide the items...
}
}
If you need to know the current position of the clicked point (e.g. to check if a tree node is clicked), you can use Control.MousePosition property. Note that MousePosition is a point in screen coordinates, so you need to call treeView1.PointToClient(position) to get the tree coordinates e.g. :
private void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
var pointClicked = this.BuildTree.PointToClient(Control.MousePosition);
var nodeClicked = this.BuildTree.GetNodeAt(pointClicked);
if (nodeClicked == null)
{
// no tree-node is clicked --> don't show the context menu
e.Cancel = true;
}
else
{
// nodeClicked variable is the clicked node;
// show/hide the context menu items accordingly
}
}
So figured out what was going wrong I was setting Visible on this.ItemMenuStrip rather than the this.BuildTree.ContextMenuStrip.
This seems rather strange to me as I would have thought BuildTree.ContextMenuStrip was just a direct reference to the ItemMenuStrip but apparently not.

How do I add a ToolTip to a control?

I would like to display a ToolTip for when the mouse is hovering over a control.
How does one create a tooltip in code, but also in the designer?
Here is your article for doing it with code
private void Form1_Load(object sender, System.EventArgs e)
{
// Create the ToolTip and associate with the Form container.
ToolTip toolTip1 = new ToolTip();
// Set up the delays for the ToolTip.
toolTip1.AutoPopDelay = 5000;
toolTip1.InitialDelay = 1000;
toolTip1.ReshowDelay = 500;
// Force the ToolTip text to be displayed whether or not the form is active.
toolTip1.ShowAlways = true;
// Set up the ToolTip text for the Button and Checkbox.
toolTip1.SetToolTip(this.button1, "My button1");
toolTip1.SetToolTip(this.checkBox1, "My checkBox1");
}
Drag a tooltip control from the toolbox onto your form. You don't really need to give it any properties other than a name. Then, in the properties of the control you wish to have a tooltip on, look for a new property with the name of the tooltip control you just added. It will by default give you a tooltip when the cursor hovers the control.
Add a ToolTip component to your form
Select one of the controls that you want a tool tip for
Open the property grid (F4), in the list you will find a property called "ToolTip on toolTip1" (or something similar). Set the desired tooltip text on that property.
Repeat 2-3 for the other controls
Done.
The trick here is that the ToolTip control is an extender control, which means that it will extend the set of properties for other controls on the form. Behind the scenes this is achieved by generating code like in Svetlozar's answer. There are other controls working in the same manner (such as the HelpProvider).
ToolTip in C# is very easy to add to almost all UI controls. You don't need to add any MouseHover event for this.
This is how to do it-
Add a ToolTip object to your form. One object is enough for the entire form.
ToolTip toolTip = new ToolTip();
Add the control to the tooltip with the desired text.
toolTip.SetToolTip(Button1,"Click here");
I did it this way: Just add the event to any control, set the control's tag, and add a conditional to handle the tooltip for the appropriate control/tag.
private void Info_MouseHover(object sender, EventArgs e)
{
Control senderObject = sender as Control;
string hoveredControl = senderObject.Tag.ToString();
// only instantiate a tooltip if the control's tag contains data
if (hoveredControl != "")
{
ToolTip info = new ToolTip
{
AutomaticDelay = 500
};
string tooltipMessage = string.Empty;
// add all conditionals here to modify message based on the tag
// of the hovered control
if (hoveredControl == "save button")
{
tooltipMessage = "This button will save stuff.";
}
info.SetToolTip(senderObject, tooltipMessage);
}
}
Just subscribe to the control's ToolTipTextNeeded event, and return e.TooltipText, much simpler.

How do you access the ScrollViewer element of a ListBox control in Silverlight/C#?

I wish to dynamically change the scroll position of a Silverlight ListBox from C#, and I need to know how to access the ScrollViewer element of a ListBox control from C#?
Thanks guys,
Jeff
From within a class that inherits from the ListBox class, you can use the Protected GetTemplateChild():
var myScrollviewer = myListBox.GetTemplateChild("ScrollViewer") as ScrollViewer;
If you want to access this from outside the ListBox, then exposing the ScrollViewer via a Property should work, again through inheritance.
CAVEAT: If you have set your own custom template, then this Scrollviewer may not exist. You can use the templates Scrollviewer name instead of the "ScrollViewer" in the method above.
Good question. I didn't find a way to do it directly, but came fairly close by looking at the Silverlight Controls project (they use the scrollviewer on the items control in some of the classes). Here is how you can get it, but it requires a custom listbox:
public class TestBox : ListBox
{
private ScrollViewer _scrollHost;
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
var itemsHost = VisualTreeHelper.GetParent(element) as Panel;
for (DependencyObject obj = itemsHost; obj != item && obj != null; obj = VisualTreeHelper.GetParent(obj))
{
ScrollViewer viewer = obj as ScrollViewer;
if (viewer != null)
{
_scrollHost = viewer;
break;
}
}
base.PrepareContainerForItemOverride(element, item);
}
}
There might be another way to hook into that event (or another way to get that panel), If you look at the template for the ListBox you will see the scroll viewer is actually named "ScrollViewer", however the GetTemplateChild method is protected so you would still need to create a custom class.
Let's make it easy...
In your Listbox template, you might find the ScrollViewer Control.
Add a Loaded Method for it, and you will get itself frome the sender arg.
private void ScrollViewer_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
myScrollViewer = (sender as ScrollViewer);
}
this works for me
You can call :
myListBox.ApplyTemplate();
to force the ListBox visual tree to be created, otherwise GetTemplateChild() will return Null if you attempt to access it immediatly.
This works well combined with "Erno de Weerd" explanation : inherit ListBox to be able to call GetTemplateChild() method.
I also tried :
to use ListBox extension method "GetScrollHost()" but it never worked for me (even after full page initialisations).
"FindName()", but it didn't work, even when i specified the ScrollViewer name into the ListBox Template.
Emmanuel (Silverlight 3)
ScrollViewer scrollViewer = yourListBox.getScrollHost();
Is null if no datasourse set to the listbox, in my case it return properly UI Element only after below code executed
myListBox.ItemsSource = list;

Categories

Resources