scroll to focused item in listbox dynamically - c#

I have two list box in WPF which looks something like this:
Lets say, the left one is lbLeft and right one is lbRight. The ">" button adds one selected item from lbLeft to lbRight. And, "<" removes the selected item form lbRight from the list. The ">>" adds all the item from lbLeft to lbRight and "<<" clears lbRight.
When I double click an item from lbLeft, it is added to the lbLeft and that newly added item is focused. Also, if i try to add an item from lbLeft which already exists in lbRight, it places a focus in that selected item(so that items are not repeated). But when lots of item are added in lbRight, I have to manually scroll down to the point where focus is placed. How can I make the scrolling of listbox automatic to the point where focus is placed?
I have done the following:
private void select_Click(object sender, RoutedEventArgs e) // > button
{
addingItemToSelectedList();
}
private void remove_Click(object sender, RoutedEventArgs e) // < button
{
if (lbRight.SelectedItem != null) {
lbRight.Items.RemoveAt(lbRight.SelectedIndex);
}
}
private void selectall_Click(object sender, RoutedEventArgs e) // >> button
{
lbRight.Items.Clear();
foreach (string item in column1) {
lbRight.Items.Add(item);
}
}
private void lbLeft_MouseDoubleClick_1(object sender, MouseButtonEventArgs e)
{
addingItemToSelectedList();
}
private void addingItemToSelectedList() {
if (lbLeft.SelectedItem != null)
{
string item = lbLeft.SelectedItem.ToString();
addFocus(item);
}
}
private void addFocus(string item) {
if (!lbRight.Items.Contains(item))
{
lbRight.Items.Add(item);
lbRight.SelectedIndex = lbRight.Items.Count - 1;
lbRight.Focus();
}
else
{
int index = lbRight.Items.IndexOf(item);
lbRight.SelectedIndex = index;
lbRight.Focus();
}
}
private void removeall_Click_1(object sender, RoutedEventArgs e) //<< button
{
lbRight.ItemsSource = null;
lbRight.Items.Clear();
}
column1 in the code is a list of items which populate lbLeft.
UPDATE:
I tried to use lbRight.ScrollIntoView(lbRight.SelectedIndex); But it has no effect

ScrollIntoView() worked now. What i had to do was:
lbRight.ScrollIntoView(lbRight.Items[lbRight.SelectedIndex]);
It now passes the actual item rather than index of it.

Related

Multiple ListBox on same Window doesn't select when focus moving ListBox

I have two ListBox in my window: LstStoreItems and LstPlayerItems. It looks like this:
The idea here is that when you select an item from the Store, the Sell button is disabled, and it UnselectAll on the Player Inventory, and vise Versa. Here's the code:
private void LstPlayerItems_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
LstStoreItems.UnselectAll();
BtnBuy.IsEnabled = false;
BtnSell.IsEnabled = true;
}
private void LstStoreItems_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
LstPlayerItems.UnselectAll();
BtnBuy.IsEnabled = true;
BtnSell.IsEnabled = false;
}
Now, though, if I select an item in the Player Inventory, and then go to select an item in the Store Inventory, it executes the code, but it doesn't actually select the item I'd clicked. How can I get it to select the item when I'm changing the focused ListBox?
I believe what is going on is the other ListBox's SelectionChanged event is being triggered when you do your UnSelectAll which is causing your new selected item to be unselected. Try checking to make sure that you have a selected item in ListBox before unselecting the items in the other ListBox.
Something like this:
private void LstPlayerItems_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (((ListBox)sender).SelectedIndex != -1)
LstStoreItems.UnselectAll();
BtnBuy.IsEnabled = false;
BtnSell.IsEnabled = true;
}
private void LstStoreItems_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (((ListBox)sender).SelectedIndex != -1)
LstPlayerItems.UnselectAll();
BtnBuy.IsEnabled = true;
BtnSell.IsEnabled = false;
}

Property returns different value than what was set

I am working on a Visual Studio extension and my current goal is to set up a menu item in the Tools menu. When clicked on this menu item will open a WinForms window containing a ListView, 3 textboxes, and a button. The idea is when you click on one of the rows in the ListView the data from that row will be populated in the textboxes so that you can update it. If you click the button a new row is added and the textboxes are cleared. However, I'm having an issue with getting the index of the row that I've selected.
private int _index;
private void newSourceBtn_Click(object sender, EventArgs e)
{
// Add new row to the ListView
ListViewItem row = new ListViewItem();
row.SubItems.Add("new");
row.SubItems.Add(String.Empty);
row.SubItems.Add(String.Empty);
remoteSourceListView.Items.Add(row);
int index = remoteSourceListView.Items.Count - 1;
remoteSourceListView.Items[index].Selected = true;
newSourceAdded = true;
sourceNameTextBox.Clear();
sourceUrlTextBox.Clear();
}
public void SourceName_TextChanged(object sender, EventArgs e)
{
remoteSourceListView.Items[IndexSelected].SubItems[1].Text = sourceNameTextBox.Text;
}
public void SourceURL_TextChanged(object sender, EventArgs e)
{
string url = sourceUrlTextBox.Text;
if ((url.StartsWith("http")) || (url.StartsWith("https")) || (url.StartsWith("git")))
{
sourceBranchTextBox.Enabled = true;
}
remoteSourceListView.Items[IndexSelected].SubItems[2].Text = url;
}
public void SourceBranch_TextChanged(object sender, EventArgs e)
{
}
public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
ListView.SelectedListViewItemCollection selectedRows = remoteSourceListView.SelectedItems;
foreach (ListViewItem row in selectedRows)
{
sourceNameTextBox.Text = row.SubItems[1].Text;
sourceUrlTextBox.Text = row.SubItems[2].Text;
IndexSelected = row.Index;
if (row.SubItems[3].Text != "")
{
sourceBranchTextBox.Enabled = true;
sourceBranchTextBox.Text = row.SubItems[3].Text;
}
}
}
public int IndexSelected
{
get { return _index; }
set { _index = value; }
}
This code shows the button click event which adds the new row to the ListView, the text changed events for each of the textboxes which updates the row in the ListView (sorta), and the selected index changed event for the ListView which is where I'm getting the index of the row that was just selected. While debugging, I noticed that when I click on a row I'm getting the correct index in the selected index changed event; however, when I call IndexSelected from either of the text changed events it is always giving me a different index.
Any suggestions?
From the code posted I can't find any reason that explain the behavior documented.
A possible reason could be the insertion/deletion of new/existing ListViewItem in a position before the saved RowIndex.
However another approach is possible. Instead of keeping the RowIndex you could try to set a global property to the ListViewItem selected and reuse this instance when you need to set its subitems.
In this way you avoid problems if the number of ListViewItems change and some item is inserted/removed before the saved RowIndex. However a safeguard against a null value should be provided.
private ListViewItem CurrentItemSelected {get;set;}
......
public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
ListView.SelectedListViewItemCollection selectedRows = remoteSourceListView.SelectedItems;
foreach (ListViewItem row in selectedRows)
{
sourceNameTextBox.Text = row.SubItems[1].Text;
sourceUrlTextBox.Text = row.SubItems[2].Text;
CurrentItemSelected = row;
if (row.SubItems[3].Text != "")
{
sourceBranchTextBox.Enabled = true;
sourceBranchTextBox.Text = row.SubItems[3].Text;
}
}
}
public void SourceName_TextChanged(object sender, EventArgs e)
{
if(CurrentItemSelected != null)
CurrentItemSelected.SubItems[1].Text = sourceNameTextBox.Text;
}
However, I am a bit perplexed by your code. Do you have the property MultiSelect set to true? Because if it is set to false then your code doesn't need to loop.
public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
if(remoteSourceListView.SelectedItems.Count > 0)
{
// With MultiSelect = false; there is only one selected item.
CurrentItemSelected = remoteSourceListView.SelectedItems[0];
sourceNameTextBox.Text = CurrentItemSelected.SubItems[1].Text;
sourceUrlTextBox.Text = CurrentItemSelected.SubItems[2].Text;
if (CurrentItemSelected.SubItems[3].Text != "")
{
sourceBranchTextBox.Enabled = true;
sourceBranchTextBox.Text = CurrentItemSelected.SubItems[3].Text;
}
}
}

How to hide the tab headers in c#?

I'm fresher to C#. I have a doubt, please anyone clarify me.
Firstly when i clicked on a button in first form, a new form should be opened with only one tab by default (basically this form will have 3 tabs).
In the default tab i will have a comboBox with list of 2 items. If i have selected a particular item, then the corresponding tab should be appeared beside
the default tab.
I have done everything but i didn't get how to hide the tab other than the default one,and how to show the corresponding tab when an item was selected from combo box. please help me.
Thank you in advance.
A TabControl has multiple TabPages, each of them having a Visible property.
(assuming you are using WinForms)
TabPage has no Visible Property, you have to remove the tab then add it again, here is a simple piece of code:
private void Form1_Load(object sender, EventArgs e)
{
List<int> myList = new List<int>() {1,2,3,4,5 };
listBox1.DataSource = myList;
foreach (var item in tabControl1.TabPages)
{
MyTabPages.Add(item as TabPage);
}
}
List<TabPage> MyTabPages = new List<TabPage>();
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (MyTabPages.Count == 0)
{
return;
}
Int32 Index = listBox1.SelectedIndex;
if (Index >= 0 && Index <= MyTabPages.Count - 1)
{
if(tabControl1.TabPages.IndexOf(MyTabPages[Index]) < 0)
{
tabControl1.TabPages.Add(MyTabPages[Index]);
}
else
{
tabControl1.TabPages.Remove(MyTabPages[Index]);
}
}
}
I Hope this helps.
These methods should help you:
public void ShowTab(TabControl tabs, TabPage page)
{
tabs.TabPages.Add(page)
}
public void HideTab(TabControl tabs, TabPage page)
{
tabs.TabPages.Remove(page)
}
A working example with a tab (tabPage1) as default tab with a comboBox control named comboBox1:
//Temporarly list to keep created tabs
List<TabPage> tempPages = new List<TabPage>();
private void Form2_Load(object sender, EventArgs e)
{
comboBox1.Items.Add("tabPage2");
comboBox1.Items.Add("tabPage3");
}
public void RemoveTabs()
{
//Remove all tabs in tempPages if there are any
if (tempPages != null)
{
foreach (var page in tempPages)
{
tabControl1.TabPages.Remove(page);
}
tempPages.Clear();
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex >= 0)
{
RemoveTabs();
var newTabName = ((ComboBox)sender).SelectedItem.ToString();
var newtab = new TabPage(newTabName);
//Create the new tabPage
tabControl1.TabPages.Add(newtab);
//Add the newly created tab to the tempPages list
tempPages.Add(newtab);
}
}

select blank row it deselect items from listview

int selectedRowIndex = 0;
private void listViewUserList_SelectedIndexChanged(object sender, EventArgs e)
{
if(listViewUserList.SelectedIndices.Count == 0)
return;
}
private void Form_Load(object sender, EventArgs e)
{
if(listViewUserList.Items.Count > 0)
{
listViewUserList.Items[selectedRowIndex].Selected = true;
listViewUserList.Select();
}
}
On form load I'm selecting first row in ListView. But when I select blank row it deselect items from ListView.
What should I do when click on blank row then select previously selected row? I have searched on Google but didn't find any good answers. Answers on stackoverflow only for WPF not for windows form.
This can be done by adding an event handler for the ListView's MouseUp event. If you still need the event handler for the SelectedIndexChanged and it's delegate method, listViewUserList_SelectedIndexChanged, remove from it any code that handles the item selection:
private void listViewUserList_SelectedIndexChanged(object sender, EventArgs e)
{
// remove the 2 lines below, as the selection handling is done in the
// MouseUp event handler
//if(listViewUserList.SelectedIndices.Count == 0)
// return;
// TODO: get the column data
}
Add the following event handler:
listViewUserList.MouseUp += new MouseEventHandler(this.listViewUserList_MouseUp);
and the following method:
private void listViewUserList_MouseUp(object sender, MouseEventArgs e)
{
if (listViewUserList.SelectedItems.Count > 0)
{
selectedRowIndex = listViewUserList.SelectedItems[0].Index;
}
else
{
listViewUserList.Items[selectedRowIndex].Selected = true;
}
}
Save the previous index in the class.
If current index points to an empty string, change the selection back to previous selection using (1)
Then call myListView.Select();
Code:
private void Form_Load(object sender, EventArgs e)
{
if(listViewUserList.Items.Count > 0 && (String.Empty != listViewUserList.Items[selectedRowIndex].ToString() ))
{
listViewUserList.Items[selectedRowIndex].Selected = true;
listViewUserList.Select();
}
}

How can i move between items in listBox and show the item name on a label.Text?

I have a listBox1 with 4 items inside. I can use the keys to move up-down between the items or click with the mouse once on each item in both cases the selected items will be highlight with blue marked .
I want when I click on an item or when I move the keys up and down over the items it will change the label.Text with the current item name.
For example in on the item moses so label1.Text will contain moses.
Moved to the next item with arrow key up so now label1.Text contain daniel.
Clicked with the mouse on the item number 3 now label1.Text will contain dana.
Tried with this:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
//listBox1.Items.Add(fsi[i].Name + Environment.NewLine);
label2.Text = listBox1.Items[i].ToString();
}
}
But its not worrking.
Works for me.
private void Form1_Load(object sender, EventArgs e)
{
listBox1.Items.Add("Item1");
listBox1.Items.Add("Item2");
listBox1.Items.Add("Item3");
listBox1.Items.Add("Item4");
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
label1.Text = listBox1.SelectedItem.ToString();
}
You really expected your code to work? Why iterate over the whole collection, if you just need to check for the currently selected item?
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
label2.Text = lbi.Content.ToString();
}
or if you're using webforms:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
label2.Text = listBox1.SelectedItem.Text;
}
If you are using List<CustomClass>/ObservableCollection<CustomClass> as ItemSource for ListBox try the following way in listbaox selected index changed event
var listTapped = sender as ListBox;
var selectedUser = listTapped.SelectedItem as CustomClass;
if (selectedUser == null)
return;
label2.Text = selectedUser.Name; //
ListBox contains event SelectedIndexChanged. It raises on such conditions. I think you should use it. Then you should use SelectedValue property to get correct string.

Categories