I have a ListView with a couple of items in it. When the ListView looses focus, the last selected ListViewItem is still "selected" with a gray background.
I would like to achieve that on ListView.FocusLost, the selection is gone and therefore the ListView.SelectedIndexChanged event will occur.
Any ideas?
I am using .NET CF 3.5.
Suppose you are accessing the ListView from a parent form/control.
You can add this piece of code in the form's/control's constructor/load event:
this.myListView.LostFocus += (s, e) => this.myListView.SelectedIndices.Clear();
Ok, so in your case, you would replace that delegate with:
if (this.myListView.SelectedIndices.Count > 0)
for (int i = 0; i < this.myListView.SelectedIndices.Count; i++)
{
this.myListView.Items[this.myListView.SelectedIndices[i]].Selected = false;
}
You can give the code a nicer form, btw.
myListView.SelectedItems.Clear();
I know this is late but in case someone else needed the solution I would like to add to the solution.
You need to set the Focused property to false to avoid deselected items having focus.
for (int i = 0; i < this.myListView.SelectedIndices.Count; i++)
{
this.myListView.Items[this.myListView.SelectedIndices[i]].Selected = false;
this.myListView.Items[this.myListView.SelectedIndices[i]].Focused = false;
}
This is easier.
this.myListView.SelectedIndex = -1;
this.myListView.Update();
Another effective way to approach this would be:
foreach (ListViewItem i in myListView.SelectedItems)
{
i.Selected = false;
}
You can try it:
MyList.ItemSelected += (sender, e) => {
((ListView)sender).SelectedItem = null;
};
or if you have the OnSelection created in your View code behind(xaml.cs):
private void OnSelection(object sender, SelectedItemChangedEventArgs e)
{
((ListView)sender).SelectedItem = null;
}
Regards
If you are using EditItemTemplate, rather than ItemTemplate, you may have been trying to figure out why ListView1.SelectedIndex = -1; hasn't been working. It's because you need to use ListView1.EditIndex = -1;
if (listView1.SelectedItems.Count > 0)
for (int i = 0; i < listView1.SelectedItems.Count; i++)
{
listView1.SelectedItems[i].Selected = false;
}
Related
I want to navigate between some TreeViewItem using back/forward buttons. I can actually do that but my problem is that i can't make it stop going outside the limits. There's an example of my code for a forward button:
private void MainUser_button_next_Click(object sender, RoutedEventArgs e)
{
int index = 0;
foreach (TreeViewItem i in TreeviewUsers.Items)
{
if (i.Equals(MainTreeView.SelectedItem))
{
break;
}
index++;
}
(TreeviewUsers.Items[index + 1] as TreeViewItem).IsSelected = true;
}
With the code I'm showing above it is possible to navigate forward but it breaks after it gets more that it's limits. I know I need to bind a limit but I don't know where to do that!
Thanks in advance!
Here's a possible answer, depending on the behavior you want
(TreeviewUsers.Item[(index+1)%TreeviewUser.Item.Count] as TreeViewitem).IsSelected = true;
or this line (try for the back case)
(TreeviewUsers.Item[mod((index+1),TreeviewUser.Item.Count)] as TreeViewitem).IsSelected = true;
and define somewhere
int mod(int x, int m) {
int r = x%m;
return r<0 ? r+m : r;
}
By the way, can't you change this code
int index = 0;
foreach (TreeViewItem i in TreeviewUsers.Items)
{
if (i.Equals(MainTreeView.SelectedItem))
{
break;
}
index++;
}
with this here
int index = TreeviewUsers.Items.Select((v, i) => new {v, i}).Where(x => x.v.Equals(MainTreeView.SelectedItem)).Select(x => x.i);
I usually figure things out but this has me beat.
I have an array of listboxes on a form and a submit button. The user can pick items from any listbox then click the submit button to choose the confirm the item, but what needs to happen is that if they select something from listbox 1 then change their mind and select something from listbox 2, the item selected in listbox 1 should become unselected.
I can code that in to the eventhandlers but the problem is as soon as I change a value in another listbox programatically it fires another event. I can't seem to logic my way out of it.
Any ideas would be great otherwise I guess I will just have to put multiple submit buttons.
EDIT:
I figured out what I think is quite an obvious and simple solution in the end. I made use of the focused property to distinguish whether the user or the program was making changes. Works for both mouse and keyboard selections.
Thanks for the suggestions...
for (int i = 0; i < treatments.Length; i = i + 1)
{
this.Controls.Add(ListBoxes[i]);
this.Controls.Add(Labels[i]);
this.Controls.Add(Spinners[i]);
Labels[i].Top = vPosition - 20;
Labels[i].Left = hPosition;
Labels[i].Width = 600;
ListBoxes[i].Left = hPosition;
ListBoxes[i].Top = vPosition;
ListBoxes[i].Width = 600;
Spinners[i].Top = vPosition + ListBoxes[i].Height;
Spinners[i].Left = hPosition + ListBoxes[i].Width - 60;
Spinners[i].Width = 40;
for (int d = 25; d > 0; d = d - 1) { Spinners[i].Items.Add((d).ToString()); }
Spinners[i].SelectedIndex = 24;
//EVENT HANDLER CODE that is executed if any selectetindexchange in any LIstbox in array
ListBoxes[i].SelectedIndexChanged += (sender, e) =>
{
for (int s = 0; s < i; s = s + 1)
{
//FIND WHICH LBs[s] IS THE SENDING LISTBOX
if (ListBoxes[s] == sender && ListBoxes[s].Focused == true)
{
string msg = "sender is ListBox " + s.ToString() + "\nFocus is" + ListBoxes[s].Focused.ToString();
// MessageBox.Show(msg);
}
else if(ListBoxes[s].Focused==false)
{
ListBoxes[s].SelectedIndex = -1;
}
}
}; //end of event handler
}
I generally solve this kind of problem with a flag that lets me know that I am changing things, so my event handlers can check the flag and not take action in that case.
private int codeChangingCount = 0;
private void combobox1_SelectedIndexChanged(object sender, EventArgs e) {
codeChangingCount++;
try {
combobox2.SelectedIndex = someNewValue;
} finally {
codeChangingCount--;
}
}
private void combobox2_SelectedIndexChanged(object sender, EventArgs e) {
if (codeChangingCount == 0) {
//I know this is changing because of the user did something, not my code above
}
}
You can do this with a simple bool instead of an int, but I like the counter approach so that I can keep incrementing codeChangingCount in nested calls and not accidentally reset it. In my production code, I have a class dedicated to this kind of flagging, and it (mis)uses IDisposable to decrement, so I can just wrap my calls in a using block, but the above snippet is simpler for illustration.
Check if Focused ListBox == ListBox2 and SelectedIndex > -1 then deselect Index[0]
if (ListBoxes[s] == sender && ListBoxes[s].Focused == true)
{
if(s == 1 && ListBoxes[s].SelectedIndex > -1) //assuming 1 is listbox2
{
ListBoxes[0].SelectedIndex = -1; // Deselect ListBox1
}
string msg = "sender is ListBox " + s.ToString() + "\nFocus is" + ListBoxes[s].Focused.ToString();
}
I am trying to do very simple thing which should work but unfortunately its not working.
I have a RichTextBox component on my Winform.
I am trying to change text value of some lines of the RichTextBox but its not changing the value. Here is my code:
private void button1_Click(object sender, EventArgs e)
{
for(int i=0; i < richTextBox1.Lines.Length; i++)
{
if(richTextBox1.Lines[i] == "ok")
{
richTextBox1.Lines[i] = "Done";
}
}
}
I put break point and I notice that it executes
richTextBox1.Lines[i] = "Done";
But it does not change the value at all.
Can anyone explain it? Why its not modifying the value?
Is there way to change/modify the value as per Line?
Thanks and Regards
According to MSDN (TextBoxBase.Lines Property):
By default, the collection of lines is a read-only copy of the lines in the TextBox. To get a writable collection of lines, use code similar to the following: textBox1.Lines = new string[] { "abcd" };
so you better go for:
for (int i = 0; i < richTextBox1.Lines.Length; i++)
{
if (richTextBox1.Lines[i] == "ok")
{
string[] lines = richTextBox1.Lines;
lines[i] = "done";
richTextBox1.Lines = lines;
}
}
UPDATE: another way of doing this (that I do not recommend though):
string line = richTextBox1.Lines[i];
richTextBox1.Find(line);
richTextBox1.SelectedText = "done";
Is it possible to set a components visible attribute based on its name?
I have 12 "master" components (comboboxes) if you want to call them that and based on the selection in these I want to display anywhere from 1 to 16 textboxes. These are named in numeric order such as combobox1_textbox_0, combobox1_textbox_1 and so on. What I would like to do ideally is take the index of the combobox and pass it as a parameter to a method that sets the textboxes visible attribute to visible/hidden depending on the index passed into the method.
Is this possible? in pseudocode or what you call it I would like it to work something like this:
private void methodToSetVisibleAttribute(int indexFromMainComboBox)
{
for(int i = 0; i < 15; i++)
{
if(i < index)
{
combobox1_textbox_+i.Visible = true;
}
else
{
combobox1_textbox_+i.Visible = false;
}
}
}
I could do panels or something for the choices but seeing as all the selections from the combobox will use the same textboxes but in different amounts it seems like alot of work to make a panel for every possible selection not to mention difficult to expand the program later on.
Assuming you are using Windows Forms and not WPF, you can use ControlCollection.Find() to find controls by name:
var textBox = this.Controls.Find(string.Format("combobox1_textbox_{0}", i), true).OfType<ComboBox>().FirstOrDefault();
if (textBox != null)
textBox.Visible = (i < index);
else
Debug.Assert(false, "textbox not found"); // Or throw an exception if you prefer.
I'll suggest an alternative to your approach, maybe not quite what you're looking for:
Place your combo boxes in a List<ComboBox> and you can access them by an index number.
List<ComboBox> myCombos = new List<ComboBox>();
for (int i = 0; i < 16; i++)
{
ComboBox cb = new ComboBox();
//do what ever you need to do here. Set its location, add items, etc.
Form1.Controls.Add(cb); //Alternatively add it to another container.
myCombos.Add(cb); //Now it's in a list.
}
Modify them like this:
for(int i = 0; i < 15; i++)
{
if(i < index)
{
myCombos[i].Visible = true;
}
else
{
myCombos[i].Visible = false;
}
}
Or even more succintly:
for(int i = 0; i < 15; i++)
{
myCombos[i].Visible = i < index;
}
I have ten labels on a page. I want to make these invisible in a for loop on page load.
I have tried this (doesn't work):
for (int i = 0; i < 10; i++)
{
my_lbl+i.Visible = false;
}
Therefore, it should do:
my_lbl1.Visible = false;
my_lbl2.Visible = false;
my_lbl3.Visible = false;
my_lbl4.Visible = false;
etc...
Is there a way to do this?
Put all of the labels into a collection:
private List<Label> labels = new List<Label>{my_lbl1, my_lbl2, my_lbl3, my_lbl4};
Then you can iterate the whole collection:
foreach(var label in labels)
label.Visible = false;
Make a List of them;
List<Label> yourlabels = new List<Label>{my_lbl1, my_lbl2, my_lbl3...};
and use foreach loop making them visible.
foreach(var label in yourlabels)
{
label.Visible = false;
}
I don't know if there is a better way but this way seems logical to me.
Putting the labels in a collection (as the previous answers have suggested) is a great solution. You can also retrieve the controls by their name using FindControl method of the Page.
for (int i = 0; i < 10; i++)
{
this.FindControl("my_lbl" + i.ToString()).Visible = false;
}
I guess you can utillize Page's FindControl method:
for (int i = 0; i < 10; i++)
{
FindControl(string.Format("my_lbl{0}", i)).Visible = false;
}
But check the case if control is not found of course.
Or, you can put them into dictionary:
Dictionary<string, Label> nameOfDict = new Dictionary<string, Label>();
nameOfDict.Add("label1", label1);
nameOfDict.Add("label2", label2);
For...
nameOfDict ["label" + incrementator].visible = false;
Or, create them dynamically into an array of labels.
If you're sure that, let's say, you want to uncheck all checkboxes in a groupbox, you can do this, too:
foreach (var item in groupBox1.Controls)
{
if (item.GetType() == typeof(CheckBox))
{
((CheckBox)item).Checked = true;
}
}
with LINQ:
foreach (var item in groupBox1.Controls.Cast<object>().Where(item => item.GetType() == typeof(CheckBox)))
{
((CheckBox)item).Checked = true;
}