Getting the text value selected in at ListBox in C# - c#

I have a list box
<Label Content="Report" HorizontalAlignment="Left" Height="47" Margin="36,75,0,0" VerticalAlignment="Top" Width="63"/>
<ListBox x:Name="ListBox1" HorizontalAlignment="Left" Height="121" Margin="84,75,0,0" VerticalAlignment="Top" Width="102" SelectionChanged="ListBox_SelectionChanged" SelectedIndex="-1">
<ListBox Height="100" Width="100" SelectionChanged="ListBox_SelectionChanged_1">
<ListBoxItem x:Name="ListBoxFAT" Content="FAT"/>
<ListBoxItem x:Name="ListBoxNUMI" Content="NUMI"/>
<ListBoxItem x:Name="ListBoxSSID" Content="SSID"/>
<ListBoxItem x:Name="ListBoxFact" Content="FACT"/>
</ListBox>
</ListBox>
This was created by dragging the listbox icon from the tool bar. I added items and their values.
Now I am trying to just get the text value of the selected item.
private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
string text = (string)ListBox1.SelectedValue;
MessageBox.Show(text);
I have also tried SelectedItem
string text = (string)ListBox1.SelectedItem;
But the message box is always blank.
This should be simple, but I have been working on it for hours, and trying every suggestion or answer on stackoverflow. Most suggestions do not even compile. For example:
string selected = listBox1.GetItemText(listBox1.SelectedValue);
Will not compile. GetItemText is not found. I am using Visual Studio 17. "'ListBox does not contain a definition for 'GetItemText'..."
Any thoughts? Please advise. Thanks.
Thanks for the comment, Charles. I did that.
Playing further, now I get
System.InvalidCastException: 'Unable to cast object of type 'System.Windows.Controls.ListBoxItem' to type 'System.String'.'
string text = (string)ListBox1.SelectedItem;

As indicated by Charles May, your XAML shows that your ListBox is within another ListBox, which is why you're getting errors being raised..
The event being called "ListBox_SelectionChanged_1" is bound to the ListBox object inside ListBox1, which is unnamed.
I believe that the behaviour you are looking for would be fixed like this:
XAML:
<Label Content="Report" HorizontalAlignment="Left" Height="47" Margin="36,75,0,0" VerticalAlignment="Top" Width="63"/>
<ListBox x:Name="ListBox1" HorizontalAlignment="Left" Height="121" Margin="84,75,0,0" VerticalAlignment="Top" Width="102" SelectionChanged="ListBox_SelectionChanged" SelectedIndex="-1">
<ListBoxItem x:Name="ListBoxFAT" Content="FAT"/>
<ListBoxItem x:Name="ListBoxNUMI" Content="NUMI"/>
<ListBoxItem x:Name="ListBoxSSID" Content="SSID"/>
<ListBoxItem x:Name="ListBoxFact" Content="FACT"/>
</ListBox>
Code Behind:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string text = ((sender as ListBox)?.SelectedItem as ListBoxItem)?.Content.ToString();
MessageBox.Show(text);
}
Or at least something close to this solution.

In the markup, SelectedIndex is set to -1 which means there is no selection. In this case, SelectedValue and SelectedItem both return null. You can solve this either by setting SelectedIndex to a value between 0 and 3 or by preparing your code to cope with a null value in SelectedValue and SelectedItem, e.g.
string text = (ListBox1.SelectedItem as ListBoxItem)?.Content?.ToString();
This won't raise an error so that the user can select an item afterwards. With a selection, the text should be displayed as expected.

Related

Cannot set SelectedIndex="0" in Xaml to ListView (Windows Store App)

I have 2 ListViews and a TextBlock. The first ListView1 includes letters in Alphabetical order. And the second ListView2 includes the words that start with the selected letter (in ListView1). When I choose a letter from ListView1 and then click on a word loaded in ListView2, I want to get the definition of this word in a TextBlock.
This is my Xaml:
<ListView
Width="510"
x:Name="ListView1"
ItemsSource="{Binding}"
Background="White"
Foreground="Black"
TabIndex="1"
Margin="-7,8,0,0"
IsSwipeEnabled="False"
SelectionChanged="ItemListView_SelectionChanged"
Grid.Row="1"
HorizontalAlignment="Left">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Grid.Row="0"
Text="{Binding glossary_letter}"
Margin="10,0,0,0"
TextWrapping="Wrap"
Foreground="Black"
FontSize="24"
FontWeight="SemiBold"
VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Width="361"
x:Name="ListView2"
Background="White"
Foreground="Black"
Margin="425,8,230,0"
Grid.Row="1"
HorizontalAlignment="Center"
ItemsSource="{Binding}"
SelectionChanged="itemListView2_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Grid.Row="1"
TextWrapping="Wrap"
Foreground="Black"
Text="{Binding}"
FontSize="24"
FontWeight="SemiBold"
VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel HorizontalAlignment="Right"
Background="White"
Width="580"
Margin="0,10,0,0" Grid.Row="1" Grid.ColumnSpan="2">
<TextBlock x:Name="defBlock" Foreground="Black" Text="{Binding glossary_definition}"></TextBlock>
</StackPanel>
If I click the first time on a letter (ListView1) then on a word (ListView2) it shows me the definition. However the second time I click on a letter, it gives me an OutOfRange Error where the ListView2.SelectedIndex = -1
This is my C# code:
private void ListView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListView2.ItemsSource = arrayW[ListView1.SelectedIndex];
}
private void ListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
defBlock.Text = arrayDef[ListView1.SelectedIndex][ListView2.SelectedIndex];
}
Any idea what is the error I am doing?
private void ListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(ListView2.SelectedIndex >= 0){
defBlock.Text = arrayDef[ListView1.SelectedIndex][ListView2.SelectedIndex];
}
else
{
defBlock.Text = arrayDef[ListView1.SelectedIndex][0];//set default selected word..
}
}
The problem
You need to manage your list2 selected index changed handler, as every time you update your list one there is a selected index change on list 2 and as there is no selected index it defaults to -1.
There's a number of ways to do this.
1.
private void ListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(ListView2.SelectedIndex == -1)
// do something or
// eg.
return;
// or
throw new IndexOutOfRangeException("Message");
//or
throw new Exception(); // catch all
}
2.
I'm not sure how you want your app to look like.
I'd be using two separate pages for this. And have the xaml for your first list view and then a second page is viewed and bound to the selected index of your first page.
So list1, you select and that then is easier to set as the data source in a new page which shows list2, and then you can update your textbox with the details from a selected item. or further, create a third page if you wanted to show more extensive details of the word and it's definition.
This way you will not have problems with your List2 having no selected index as the data source is changed.
3.
Or,
Take the binding declarations out of the index changed handler and call them methodically when an index is in List1 is selected.So when the selection of List1 is changed, List 2 is updated in other words, you need to update your data source. edit: and with this it's another way of you controlling the use of error handling to avoid an outofrange exception, as the datasource is updated.
So possibly put the following into a separate method.
private void MyTextMethod(){
defBlock.Text = arrayDef[ListView1.SelectedIndex][ListView2.SelectedIndex];
}
private void ListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try{
MyTextMethod)();
}
catch(OutOfRangeException){
// do something.
}
}
out of your selected index changed handler and make a call to a separate method when from within the handler.
4.
Take your binding declaration for list2 from out of your selectedindex change handler for list1.
So you could have a method that will update the binding source of list2 and manage the selected index changed handler. Though this is the least useful suggestion.
Bottom line: You need to have some try and catch, or throw statement managing the outofrange exception, as the second list will have varying lengths and the index on letter As list may be selected at 10, and then the letter X may only have a list of length 1 and there is always the issue of the selectionchange returning a selection of -1.
( You don't actually need to clear list2, it is cleared automatically as the data source is changed (sorry, I didn't make that clear))

How can I add from a CheckBoxList to a List<>?

I have for instance a list of 5 checkbox items:
<ListBox x:Name="Listbox" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top">
<CheckBox x:Name="Item1" Content="Item1" Checked="Item1_Checked"/>
<CheckBox x:Name="Item2" Content="Item2" Checked="Item2_Checked"/>
<CheckBox x:Name="Item3" Content="Item3" Checked="Item3_Checked"/>
<CheckBox x:Name="Item4" Content="Item4" Checked="Item4_Checked"/>
<CheckBox x:Name="Item5" Content="Item5" Checked="Item5_Checked"/>
</ListBox>
For every checkbox that is checked, I want the item to be added to a list called myList.
So I tried this:
public MainWindow()
{
InitializeComponent();
}
List<string> myList;
private void Item1_Checked(object sender, RoutedEventArgs e)
{
myList.Add(Item1);
}
Problem is, "Item1" isn't an object so it can't be added to a list of objects.
After I have some objects in my list, I want to sort them in a specific order, for example by name, and than display the list in a pre-made templates.
Any suggestions?
Hope that you understand me, my english is not perfect and I'm new to c# and wpf :P
You need to use the Source property of the RoutedEventsArgs parameter passed to the checked handler. Also, you can use the same event handler for all checkboxes:
<ListBox x:Name="Listbox" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top">
<CheckBox x:Name="Item1" Content="Item1" Checked="Item_Checked"/>
<CheckBox x:Name="Item2" Content="Item2" Checked="Item_Checked"/>
<CheckBox x:Name="Item3" Content="Item3" Checked="Item_Checked"/>
<CheckBox x:Name="Item4" Content="Item4" Checked="Item_Checked"/>
<CheckBox x:Name="Item5" Content="Item5" Checked="Item_Checked"/>
</ListBox>
private void Item_Checked(object sender, RoutedEventArgs e)
{
myList.Add((e.Source as CheckBox).Name);
}
The control that initiated the event can be found in RoutedEventArgs.Source. You need to cast it, of course, to the control type.
In your particular case you can also use sender, but it's typically safer to rely on the Source property.

Hold Event Longlistselector

Hej
I want to create a standard holdevent. When you hold an element, there would appear some options you could chose like a new list.
How do you create this, is it just simply done with a popup or is there a smarter way?
Extra
After finding the answer, see answer below, some nice info is:
Put the context creation inside the hold event.
Then you can change to different contextmenus depending on the item. You can get the item that was holded by the following
private void StackPanel_Hold(object sender, GestureEventArgs e)
{
ItemViewModel itemViewModel = (sender as StackPanel).DataContext as ItemViewModel;
string t = itemViewModel.LineOne;
}
And
<ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding Items}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Height="78" Hold="StackPanel_Hold">
<TextBlock Text="{Binding LineOne}" />
<TextBlock Text="{Binding LineTwo}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
A good link for easy implementation is also youtube link below, replicated here :
Youtube
A ContextMenu is one option..
http://blogs.msdn.com/b/msgulfcommunity/archive/2013/05/19/windows-phone-toolkit-context-menu-getting-selected-item-within-a-long-list-selector.aspx

wpf ListBox Control: simple GetSelectedValue / item-value

List box is not binded just a Combobox replacement (values are exposed)
Xaml
<ListBox SelectionChanged="LBX_AddTaskOptions_SelectionChanged" HorizontalAlignment="Left" Margin="19,29,0,0" Name="LBX_AddTaskOptions" VerticalAlignment="Top" Width="125" FontWeight="Bold" Background="Beige">
<ListBoxItem Background="Beige" FontWeight="Bold" v>
<StackPanel Orientation="Horizontal">
<TextBlock Text="internet"></TextBlock>
<Image Source="Images\IE_BlackRed.png" Height="30"></Image>
</StackPanel>
</ListBoxItem>
<ListBoxItem Background="Beige" FontWeight="Bold">
<StackPanel Orientation="Horizontal">
<TextBlock Text="localFolder"></TextBlock>
<Image Source="Images\Folder_Black.png" Height="30"></Image>
</StackPanel>
</ListBoxItem>
</ListBox>
CodeBehind
private void LBX_AddTaskOptions_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var SelItm = LBX_AddTaskOptions.SelectedItem.ToString();
MessageBox.Show(Sel);
}
i have searched for that question, though answers are only for complex issues
as i am fresh .net Developer, i know all methods to extract DDL text/value
i even made extentions , though couldn't figure how to do this simple value extraction
shouldn't it be simple ?
messageBox shows the name of control (:
This isn't quite the right approach for XAML. You don't want to list out the markup for each item -- instead, use an ItemTemplate to define how it should look, and use bindings to render the actual item:
<ListBox SelectionChanged="LBX_AddTaskOptions_SelectionChanged" Name="LBX_AddTaskOptions">
<ListBox.ItemTemplate>
<ListBoxItem Background="Beige" FontWeight="Bold" v>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
<Image Source="Images\IE_BlackRed.png" Height="30" />
</StackPanel>
</ListBoxItem>
</ListBox.ItemTemplate>
</ListBox>
Bind the ListBox ItemsSource to the model data itself (ie, the array of strings in this case). Now, eventually you'll probably want to use a view model, but you can also add the items from code behind on load:
string[] ListBoxItems = new string[] { "internet", "local folder" };
LBX_AddTaskOptions.ItemsSource = ListBoxItems;
This should result in SelectedValue giving you the correct value.
Footnote -- you could get the selected value using the markup you've written out in the question -- but it would be ugly and would defeat the whole purpose of XAML. You'd need to cast SelectedItem to a ListBoxItem, then get its child and cast that to a StackPanel, get its children, etc, you get the idea. And then, of course, if the markup changes at all, the code you just wrote is no longer valid.
The item that you are getting in your selected value is a ListBoxItem with a control inside it. If you want to extract the value like the text then you have to do this
private void LBX_AddTaskOptions_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var SelItm = LBX_AddTaskOptions.SelectedItem as ListBoxItem;
var StackPanel = SelItm.Content as StackPanel;
foreach (var child in StackPanel.Children)
{
if(child is TextBlock)
{
MessageBox.Show((child as TextBlock).Text);
}
}
}
You have to sort of dig into the control to get the actual text. There are a lot of ways to get the value but this is the pretty basic one.
Calling ToString() method will just convert the current object as a string which is a ListBoxItem.

Why is my Button event is not occuring?

I am having an issue with my button event not occuring
Basically I have cart items that are listed in the listbox. When the delete button is clicked then the item is deleted from the list box.
I tried debugging, but it seems to not even call the method for when the button is clicked.
In my ticketscreen.xaml file I specify my button in the template:
<DataTemplate x:Key="TicketTemplate">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Height="50">
...
<Button Name="Remove" Width="35" Height="35"
FontFamily="Resources/#charlemagnestd-regular.otf" FontSize="24"
Click="removeCartItem" Grid.Column="5"
MouseMove="Remove_MouseMove">X</Button>
...
</StackPanel>
</DataTemplate>
My List box is the following:
<ListBox Name="TicketItems" ItemsSource="{Binding}"
ItemTemplate="{StaticResource TicketTemplate}"
Grid.Row="3" Grid.ColumnSpan="6" Background="Transparent"
BorderBrush="Transparent" IsHitTestVisible="False">
</ListBox>
My method removeCartItem is in the ticketscreen.xaml.cs:
private void removeCartItem(object sender, RoutedEventArgs e)
{
Console.WriteLine("TestingCartRemove");
}
Am I missing something obvious?
Thx in adv! :)
Edit:
There seems to be something infront of it... maybe the listbox? How do I make it so that I am not clicking the ListBox, but I can click on things within the Stackpanel, which are contents of the list box.
IsHitTestVisible="False" for the ListBox is disabling the click event for the Button. It makes all content within the ListBox invisible to hit-test as well.
Are you sure is not firing? Maybe you haven't seen the output in Visual Studio Output Window. Try to call a MessageBox.Show("Test"); instead.
You have a listbox control, which leads me to believe that this is not a console application. Therefore, Console.WriteLine() will not show you anything. Try MessageBox.Show() instead.

Categories

Resources