C# contextmenustrip doesn't show any indication if any item is selected - c#

I have added a context menu strip 'View' on my listview with some menu items, like Large icons/ Small icons/ Tiles.
Now whenever I select any of the options the respective view changes, but the menu doesn't get any Mark/ indication like that happens in Windows file explorer, where it shows bullet/ dot against the selected menu item.
Can someone please show, how I can get the similar dot/ bullet for my context menu?
I have tried CheckOnClick property which gets me a tick mark, but is there any other way that I could get that dot there?
Thanks in advance!

I couldn't find a way to get bullets/ dots like Windows File Explored's View options, but I used below logic and used checked states to indicate the selections made.
private void toolStripViewOptions_Click(object sender, EventArgs e)
{
ToolStripMenuItem selectedOption = sender as ToolStripMenuItem;
SetIndicationForSelectedOption(selectedOption);
}
private void SetIndicationForSelectedOption(ToolStripMenuItem selectedMenuItem)
{
ToolStripItemCollection menuItems = (contextMenuStrip.Items[(Int32)toolStripView.Tag] as ToolStripMenuItem).DropDownItems;
// Set checked state for only the selected view option and disable same for others.
foreach (ToolStripMenuItem item in menuItems)
{
if (selectedMenuItem == item)
selectedMenuItem.Checked = true;
else
item.Checked = false;
}
}
This worked for my requirement.

Related

Which Item is user focused in listview xamarin forms

I am a student learning xamarin forms, I am trying to create a basic chat app in this I want to know how to get position of current item in listview that's user watching. When a new message received i want to know if user is at bottom or not if at bottom focus the new and if not at the bottom then just add not by adding focus to it.
you get the selected item from the Xamarin.Forms.ListView.SelectedItem property of your ListView.
If your ListView.ItemSource is of a type that allows using IndexOf you can now do something like
int position = (yourlistview.ItemSource as ObservableCollection<your type>).IndexOf(yourlistview.SelectedItem)
Update:
ok I think i understood what you want.
In most cases more than one item is currently shown when using a listview. So their exists not a single index
but i think you just want to know if the last item of the list is visible/the user has scrolled to the end?
If so ListView has an ItemAppearing event. I use it for example to load more data from an websource if the user scrolled through the first 100 items.
You could do something like this
listview.ItemAppearing += listviewItemAppearing;
listview.ItemDisappearing += listviewItemDisappearing;
bool m_scrolledToEnd;
private void listviewItemDisappearing(object sender, ItemVisibilityEventArgs e)
{
if(e.Item == yourlastiem)
m_scrolledToEnd = false;
}
private void listviewItemAppearing(object sender, ItemVisibilityEventArgs e)
{
if(e.Item == yourlastiem)
m_scrolledToEnd = true;
}
if you realy need to know if a specific index is shown you could create a List<int> m_idxlist;
and in the appearing event add the index of the item to the list
and in the disappearing event remove the index of the item from the list.
Then you will have a list where all indexes of the items currently shown are stored.
From the Documentation
ListView supports selection of one item at a time. Selection is on by
default. When a user taps an item, two events are fired: ItemTapped
and ItemSelected. Note that tapping the same item twice will not fire
multiple ItemSelected events, but will fire multiple ItemTapped
events. Also note that ItemSelected will be called if an item is
deselected.
To detect selecting an item, you can add a method, onSelection:
void OnSelection (object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null) {
return; //ItemSelected is called on deselection, which results in SelectedItem being set to null
}
DisplayAlert ("Item Selected", e.SelectedItem.ToString (), "Ok");
//((ListView)sender).SelectedItem = null; //uncomment line if you want to disable the visual selection state.
}
To disable selection just set the selectedItem to null:
SelectionDemoList.ItemSelected += (sender, e) => {
((ListView)sender).SelectedItem = null;
};

How to deselect all MenuStripItems?

I'm trying to make sort of a selector/last detector in my menustrip. Essentially I have a bunch of "sub items" under one menu strip item. And I want to go through all of them, uncheck them, and then check only the one that was clicked.
Essentially I want to uncheck all of the stuff that starts with de_ (and that last one, so all of them)
Edit: Got it to work, here is the code I ended up using
private void ItemClick(object sender, EventArgs e)
{
foreach (ToolStripMenuItem item in mapsToolStripMenuItem.DropDownItems)
{
item.Checked = false;
}
((ToolStripMenuItem)sender).Checked = true;
}
But I'm not sure what to replace that ? with in order to look into the right place.
Try using the parent menu's DropDownItems collection:
foreach (ToolStripMenuItem item in mapStripMenuItem.DropDownItems ) {
item.Checked = false;
}
From you image, it should be named Map-something, I'm guessing.

How to change listview selected row backcolor even when focus on another control?

I have a program which uses a barcode scanner as input device so that means I need to keep the focus on a text box.
The program has a listview control and I select one of the items programatically when a certain barcode is scanned. I set the background color of the row by:
listviewitem.BackColor = Color.LightSteelBlue;
Things I have tried:
listview.HideSelection set to false
call listview.Focus() after setting the color
listviewitem.Focused set to true
call listview.Invalidate
call listview.Update()
call listview.Refresh()
different combinations of the above
I've also did combinations above stuff in a timer so that they are called on a different thread but still no success.
Any ideas?
More info:
The key here is the control focus. The listview control does not have the focus when I select one of the items.
I select one item by doing:
listView1.Items[index].Selected = true;
the Focus is always in the textbox.
the computer does not have keyboard or mouse, only a barcode reader.
I have this code to keep the focus on the textbox:
private void txtBarcode_Leave(object sender, EventArgs e)
{
this.txtBarcode.Focus();
}
You need to have a textbox add that code to simulate my problem.
What you describe works exactly as expected, assuming that you've set the HideSelection property of the ListView control to False. Here's a screenshot for demonstration purposes. I created a blank project, added a ListView control and a TextBox control to a form, added some sample items to the ListView, set its view to "Details" (although this works in any view), and set HideSelection to false. I handled the TextBox.Leave event just as you showed in the question, and added some simple logic to select the corresponding ListViewItem whenever its name was entered into the TextBox. Notice that "Test Item Six" is selected in the ListView:
Now, as I suspected initially, you're going to mess things up if you go monkeying around with setting the BackColor property yourself. I'm not sure why you would ever want to do this, as the control already uses the default selection colors to indicate selected items by default. If you want to use different colors, you should change your Windows theme, rather than trying to write code to do it.
In fact, if I add the line item.BackColor = Color.LightSteelBlue in addition to my existing code to select the ListViewItem corresponding to the name typed into the TextBox, I get exactly the same thing as shown above. The background color of the item doesn't change until you set focus to the control. That's the expected behavior, as selected items look different when they have the focus than they do when their parent control is unfocused. Selected items on focused controls are painted with the system highlight color; selected items on unfocused controls are painted with the system 3D color. Otherwise, it would be impossible to tell whether or not the ListView control had the focus. Moreover, any custom BackColor property is completely ignored by the operating system when the ListView control has the focus. The background gets painted in the default system highlight color.
Explicitly setting the focus to the ListView control, of course, causes the custom background color to be applied to the ListViewItem, and things render with a color that very much contrasts with the color scheme that I've selected on my computer (remember, not everyone uses the defaults). The problem, though, becomes immediately obvious: you can't set the focus to the ListView control because of the code you've written in the TextBox.Leave event handler method!
I can tell you right now that setting the focus in a focus-changing event is the wrong thing to do. It's a hard rule in Windows you're not allowed to do things like that, and the documentation even warns you explicitly not to do it. Presumably, your answer will be something along the lines of "I have to", but that's no excuse. If everything were working as expected, you wouldn't be asking this question in the first place.
So, what now? Your application's design is broken. I suggest fixing it. Don't try and monkey with setting the BackColor property yourself to indicate that an item is selected. It conflicts with the default way that Windows highlights selected items. Also, don't try and set the focus in a focus-changing event. Windows explicitly forbids this, and the documentation is clear that you're not supposed to do this. If the target computer doesn't have a mouse or keyboard, it's unclear how the user is going to set focus to anything else in the first place, unless you write code to do it, which you shouldn't be doing.
But I have surprisingly little faith that you'll want to fix your application. People who ignore warnings in the documentation tend to be the same people who don't listen to well-meaning advice on Q&A sites. So I'll throw you a bone and tell you how to get the effect you desire anyway. The key lies in not setting the ListViewItem's Selected property, which avoids the conflict between your custom BackColor and the system default highlight color. It also frees you from having to explicitly set the focus to the ListView control and back again (which, as we established above, isn't actually happening, given your Leave event handler method). Doing that produces the following result:
And here's the codeā€”it's not very pretty, but this is just a proof of concept, not a sample of best practice:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
listView1.View = View.Details;
listView1.HideSelection = false;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
foreach (ListViewItem item in listView1.Items)
{
if (item.Text == textBox1.Text)
{
item.BackColor = Color.LightSteelBlue;
return;
}
}
}
private void textBox1_Leave(object sender, EventArgs e)
{
this.textBox1.Focus();
}
}
A standard ListView does not let you set the background color of a selected row. The background (and foreground) colors of a selected row are always controlled by the theme of the OS.
You have to owner draw your ListView to get around this OR you can use ObjectListView. ObjectListView is an open source wrapper around .NET WinForms ListView, which makes it much easier to use, as well as easily allowing things that are very difficult in a normal ListView -- like changed the colors of selected rows.
this.objectListView1.UseCustomSelectionColors = true;
this.objectListView1.HighlightBackgroundColor = Color.Lime;
this.objectListView1.UnfocusedHighlightBackgroundColor = Color.Lime;
This shows the ObjectListView when it does not have focus.
Here's a solution for a ListView that does not allow multiple selections and
does not have images (e.g. checkboxes).
Set event handlers for the ListView (in this example it's named listView1):
DrawItem
Leave (invoked when the ListView's focus is lost)
Declare a global int variable (i.e. a member of the Form that contains the ListView,
in this example it's named gListView1LostFocusItem) and assign it the value -1
int gListView1LostFocusItem = -1;
Implement the event handlers as follows:
private void listView1_Leave(object sender, EventArgs e)
{
// Set the global int variable (gListView1LostFocusItem) to
// the index of the selected item that just lost focus
gListView1LostFocusItem = listView1.FocusedItem.Index;
}
private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
// If this item is the selected item
if (e.Item.Selected)
{
// If the selected item just lost the focus
if (gListView1LostFocusItem == e.Item.Index)
{
// Set the colors to whatever you want (I would suggest
// something less intense than the colors used for the
// selected item when it has focus)
e.Item.ForeColor = Color.Black;
e.Item.BackColor = Color.LightBlue;
// Indicate that this action does not need to be performed
// again (until the next time the selected item loses focus)
gListView1LostFocusItem = -1;
}
else if (listView1.Focused) // If the selected item has focus
{
// Set the colors to the normal colors for a selected item
e.Item.ForeColor = SystemColors.HighlightText;
e.Item.BackColor = SystemColors.Highlight;
}
}
else
{
// Set the normal colors for items that are not selected
e.Item.ForeColor = listView1.ForeColor;
e.Item.BackColor = listView1.BackColor;
}
e.DrawBackground();
e.DrawText();
}
Note: This solution will result in some flicker. A fix for this involves subclassing the ListView control so you
can change the protected property DoubleBuffered to true.
public class ListViewEx : ListView
{
public ListViewEx() : base()
{
this.DoubleBuffered = true;
}
}
On SelectedIndexChanged:
private void lBxDostepneOpcje_SelectedIndexChanged(object sender, EventArgs e)
{
ListViewItem item = lBxDostepneOpcje.FocusedItem as ListViewItem;
ListView.SelectedIndexCollection lista = lBxDostepneOpcje.SelectedIndices;
foreach (Int32 i in lista)
{
lBxDostepneOpcje.Items[i].BackColor = Color.White;
}
if (item != null)
{
item.Selected = false;
if (item.Index == 0)
{
}
else
{
lBxDostepneOpcje.Items[item.Index-1].BackColor = Color.White;
}
if (lBxDostepneOpcje.Items[item.Index].Focused == true)
{
lBxDostepneOpcje.Items[item.Index].BackColor = Color.LightGreen;
if (item.Index < lBxDostepneOpcje.Items.Count-1)
{
lBxDostepneOpcje.Items[item.Index + 1].BackColor = Color.White;
}
}
else if (lBxDostepneOpcje.Items[item.Index].Focused == false)
{
lBxDostepneOpcje.Items[item.Index].BackColor = Color.Blue;
}
}
}
You cant set focus on listview control in this situation. txtBarcode_Leave method will prevent this. But if you are desire to be able select listview items by clicking on them, just add code below to MouseClick event handler of listview:
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
ListView list = sender as ListView;
for (int i = 0; i < list.Items.Count; i++)
{
if (list.Items[i].Bounds.Contains(e.Location) == true)
{
list.Items[i].BackColor = Color.Blue; // highlighted item
}
else
{
list.Items[i].BackColor = SystemColors.Window; // normal item
}
}
}
This change color of selected item. but only in state listview not have focus.
Make sure HideSelection is !TRUE! and simple use this code:
private void ListView_SelectedIndexChanged(object sender, EventArgs e){
foreach(ListViewItem it in ListView.Items)
{
if (it.Selected && it.BackColor != SystemColors.Highlight)
{
it.BackColor = SystemColors.Highlight;
it.ForeColor = SystemColors.HighlightText;
}
if (!it.Selected && it.BackColor != SystemColors.Window)
{
it.BackColor = SystemColors.Window;
it.ForeColor = SystemColors.WindowText;
}
}
}
Just do like this:
Set property UnfocusedHighlighForegroundColor = "Blue"
Set property UnfocusedHighlighBackgroundColor = "White"
Set property UserCustomSelectionColors = true
Good luck :)

C# how do I ensure the selected node remains highlighted when focus lost

I have changed the Treeview.HideSelection = false;
But how do I insure that when focus is lost that the selected item remains the original selected color?
EDIT:
I have a listview on a form that holds a list of process events. Alongside the Treeview on the same form is a series of selections that the user completes to classify the event in the listview. However, when the user makes a selection on one of the classification controls the blue highlighted selected Treeview item turns to a grey color. I was hoping to find the property that defines this color to make it the same color blue.
Any suggestions.
Update:
public partial class myTreeView : TreeView
{
TreeNode tn = null;
public myTreeView()
{
InitializeComponent();
}
protected override void OnAfterSelect(TreeViewEventArgs e)
{
if (tn != null)
{
tn.BackColor = this.BackColor;
tn.ForeColor = this.ForeColor;
}
tn = e.Node;
base.OnAfterSelect(e);
}
protected override void OnBeforeSelect(TreeViewCancelEventArgs e)
{
e.Node.BackColor = Color.Green;
e.Node.ForeColor = Color.White;
base.OnBeforeSelect(e);
}
protected override void OnGotFocus(System.EventArgs e)
{
base.OnGotFocus(e);
}
protected override void OnLostFocus(System.EventArgs e)
{
if (tn != null)
{
tn.BackColor = Color.Green;
tn.ForeColor = Color.White;
}
// tn.BackColor = Color.Red;
base.OnLostFocus(e);
}
}
Setting ListView.HideSelection to true means that when focus is lost, it will hide the selection. By setting HideSelection to false, the selected item will still have the color indicator showing which item is selected.
Generally, you don't. The change in color is one of the visual cues that indicate which control has the focus. Don't confuse your customers by getting rid of that.
If you want to buck the convention, then you can make your control owner-drawn, and then you can paint the items whatever color you want.
Another option, in your case, is to use a drop-down combo box instead of a list box. Then the current selection is always clear, no matter whether the control has the focus. Or, you could consider using a grid, where each event has all its settings given separately, and then "selection" doesn't matter at all.
If I were doing it, I would simply have an extra Label alongside the ListView, above the classification controls being selected, that would indicate which process event has been selected. You can also use said Label to add extra details about the event (if any).
This way, you are sticking to standard UI conventions and making it that much clearer to the user what their current selection is.
I use this code; it works for me.
design: Mytreeview.HideSelection = True you will manual highlight the lose focus selected node.
Private Sub MyTreeview_Leave(sender As Object, e As EventArgs) Handles MyTreeview.Leave
MyTreeview.SelectedNode.BackColor = Color.LemonChiffon
End Sub
Private Sub MyTreeview_BeforeSelect(sender As Object, e As TreeViewCancelEventArgs) Handles MyTreeview.BeforeSelect
If MyTreeview.SelectedNode IsNot Nothing Then
MyTreeview.SelectedNode.BackColor = Color.White
End Sub
I like the HideSelection = false; answer, because:
It's easy
I have a search function that cycles through the nodes and marks the relevant ones by changing it's background to yellow, when the user clicks on the node a textbox fills with the relevant info attached to that node, before I used this method, if the user clicked on the textbox to scroll through it, it would unhighlight the node and make it hard to keep track of which node was selected, this way it is still highlighted in a light gray colour showing it is not in focus, opposed to the blue highlight which is used when it is in focus. I could have 'painted' the node but with the yellow background for search results would have made life more complicated than it needed to be.
Did I mention it was easy?

Dynamically add items to a Context Menu & set Click action

I have a List of strings that is regenerated every 5 seconds. I want to create a Context Menu and set its items dynamically using this list.
The problem is that I don't have even a clue how to do that and manage the Click action for every item generated (which should use the same method with different parameter DoSomething("item_name")).
How should I do this?
Thanks for your time.
Best regards.
So, you can clear the items from the context menu with:
myContextMenuStrip.Items.Clear();
You can add an item by calling:
myContextMenuStrip.Items.Add(myString);
The context menu has an ItemClicked event. Your handler could look like so:
private void myContextMenuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
DoSomething(e.ClickedItem.Text);
}
Seems to work OK for me. Let me know if I misunderstood your question.
Another alternative using a ToolStripMenuItem object:
//////////// Create a new "ToolStripMenuItem" object:
ToolStripMenuItem newMenuItem= new ToolStripMenuItem();
//////////// Set a name, for identification purposes:
newMenuItem.Name = "nameOfMenuItem";
//////////// Sets the text that will appear in the new context menu option:
newMenuItem.Text = "This is another option!";
//////////// Add this new item to your context menu:
myContextMenuStrip.Items.Add(newMenuItem);
Inside the ItemClicked event of your myContextMenuStrip, you can check which option has been chosen (based on the name property of the menu item)
private void myContextMenuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
ToolStripItem item = e.ClickedItem;
//////////// This will show "nameOfMenuItem":
MessageBox.Show(item.Name, "And the clicked option is...");
}

Categories