Windows 10 uwp listview selection changed not working - c#

Windows 10 uwp app with a listview to just list out strings. First of all, I have an observable collection of strings in my xaml code behind. Because I still dont understand proper data binding in xaml, I am currently adding the strings to tje listview by doing a foreach loop on the observable collection and then doing
Listview1.Items.Add (new TextBlock {Text = myString});
However, is binding in this case as easy as setting my listview ItemsSource to my observablecollection?
My main issue though is I want to know when a user selects a string in the listview and what string they selected. So, I wired up to the listview SelectionChanged event. This event will raise when I select an item in the list, however
var selectedString = e.AddedItems.First().ToString();
Does not give me the selected string value. Also, there seems to be a possible recursion issue with this event. At one point, my breakpoint hit twice even though I had only selected an item in the listview one time.
So, main question is how to i get the selected string from the listview but also would appreciate suggestions or comments on data binding and if there could be recursion with this event.
EDIT: After trying the last two answers, I am still having some issues here. I cannot get the string that is selected. Using both answers below, I get the same results. First, there is some recursion because clearly the event does fire twice most times even when the list is selected only one time. Also, in both cases, the string is never populated with the selection. In fact, the breakpoint will hit at the line but then skip to the end of the event handler method and I cannot inspect any of the variables or arguments. I even wrapped it up in a try catch block but it never runs the rest of the code in the try block and never catches an exception. All it does is skip to the end of the event handler method but then take me to a file called SharedStubs.g.cs and in there, it hits at the end of this method
// Signature, Windows.UI.Xaml.UnhandledExceptionEventHandler.Invoke, [rev] [return] [Mcg.CodeGen.ComHRESULTReturnMarshaller] void__int, [rev] [in] [Mcg.CodeGen.WinRTInspectableMarshaller] object____mcg_IInspectable, [rev] [in] [GenericTypeMarshaller] -> T,
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
[global::System.Runtime.InteropServices.McgGeneratedMarshallingCode]
internal static int Proc_object__TArg0__<TArg0>(
object __this,
global::System.Runtime.InteropServices.__vtable_IInspectable* unsafe_sender,
void* unsafe_e,
global::System.IntPtr __methodPtr)
{
// Setup
object sender = default(object);
TArg0 TArg0__arg = default(TArg0);
try
{
// Marshalling
sender = global::System.Runtime.InteropServices.McgMarshal.IInspectableToObject(((global::System.IntPtr)unsafe_sender));
TArg0__arg = (TArg0)global::System.Runtime.InteropServices.McgModuleManager.ComInterfaceToObject(
((global::System.IntPtr)unsafe_e),
typeof(TArg0).TypeHandle
);
// Call to managed method
global::McgInterop.Intrinsics.HasThisCall__Proc_object__TArg0__<TArg0>(
__this,
__methodPtr,
sender,
TArg0__arg
);
global::System.Runtime.InteropServices.DebugAnnotations.PreviousCallContainsUserCode();
// Return
return global::McgInterop.Helpers.S_OK;
}
catch (global::System.Exception hrExcep)
{
// ExceptionReturn
return global::System.Runtime.InteropServices.McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
}
And the sender in this method is ListView. After it hits in this method, the debugger just sort of hangs. I never get a real exception or error and it never really stops. I can hit continue but it just sits idle. So, the above is the only clue I really have. Not sure why this would hit but not the try/catch block and why I would never get any further exception, stack trace, etc...
Thanks!

Can you please try this one?
private void Listview1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
TextBlock textBlock = (sender as ListView).SelectedItem as TextBlock;
string value = textBlock.Text;
// OR
string value2 = (e.AddedItems[0] as TextBlock).Text;
// OR
string value3 = (e.AddedItems.First() as TextBlock).Text;
}

First of all, binding string items to a listview requires one line of code. You don't have to create a XAML template for that since you're not binding a object with properties. You can just do this:
Listview1.ItemsSource = YourObservableCollection();
It will bind your collection to your ListView.
As for the selection event, instead of SelectionChanged, you can use ItemClick event. The event args will give you the selected item aka the string by calling e.ClickedItem.
First, enable your ListView1's IsItemClickEnabled. Set it from false to true. Then add the ItemClick event.
private void ListView1_ItemClick(object sender, ItemClickEventArgs e)
{
e.ClickedItem;
}
This will return the value selected, in your case, the string.
Hope it helps!

You get the currently selected item in a ListView using the SelectedItem property and since you are adding TextBlock elements to the Items collection you should cast the SelectedItem property to a TextBlock and then access its Text property to get the string value:
private void Listview1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
TextBlock textBlock = Listview1.SelectedItem as TextBlock;
if (textBlock != null)
{
string s = textBlock.Text;
}
}

you can also use SelectionChanged event to get the value selected by user.
Here is how the code will look like :
In XAML :
ListView Name="sourceList"
ItemsSource="{Binding itemsource}"
SelectionChanged="sourceList_SelectionChanged"
In Code behind :
private void sourceList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string selectedSource = Convert.ToString(((ListView)sender).SelectedItem);
}

Related

C# WinForms ListBox changes selection to first item

I got a problem with a ListBox in a WinForm application. I have two ListBoxes inside of a tab control and depending on the selection in the first one (lb1), the DataSource of the second one (lb2) changes. This is done in the SelectedValueChanged Event.
private void listBox_ControlUnits_SelectedValueChanged(object sender, EventArgs e)
{
ControlUnit unit = (sender as ListBox).SelectedItem as ControlUnit;
textBox_ProjectNameTab.Text = unit.ProjectName;
listBox_ControlCircuits.DataSource = null;
listBox_ControlCircuits.DataSource = unit.ControlCircuits;
}
lb1 is filled with a DataSource, too.
Now if I select a value in lb1 the selection automatically jumps back to the first item and I can not figure out why. is this some kind of UI update problem?
Even without the SelectedValueChanged event and the connection to the second listbox the issue occures.
Short gif of the problem, sorry for the blurriness
If I select one item more than once it works somehow (as seen in the gif).
Edit:
I found the problem but I do not quite understand what happens.
I have another listBox on another tab of my tab control. This listBox has the same DataSource as lb1. This seems to cause this behavior.
I finally found the problem:
I did not know that if I use the same DataSource for two ListBoxes they share the BindingContext per default.
I created a new BindingContext for the second ListBox and now the selection does no longer change.
listBox_allGroups.DataSource = null;
listBox_allGroups.DataSource = x.y;
listBox_allGroups.DisplayMember = "Name";
listBox_ControlUnits.DataSource = null;
listBox_ControlUnits.DataSource = x.y;
listBox_ControlUnits.DisplayMember = "Name";
listBox_ControlUnits.BindingContext = new BindingContext();
You can use a variable to hold the selected item
object _selecteditem=null;
and check it in ListBox click event.
prive void ListBox1_Click(object sender,EventArgs e)
{
if(ListBox1.SelectItem == _selecteditem) return;
// do ...
}

How to test which combobox has been most recently changed? WPF

Is there a way to check to see which combobox which value has been most recently changed?
how to check if item is selected from a comboBox in C#
I know you can do this,
if (MyComboBox.SelectedIndex >= 0)
{
//do stuff
}
The problem I am having is that I am combining Event Handlers in to one handler due to the amount of comboboxes and having one event for each combobox really is not practical if I can help it.
Is there a way to have a variable assigned giving you the name of the combobox which value has been most recently changed? Or will I have to use individual event handlers for each combobox?
Actually It will be very easy to track most recent combobox change when you using single event handler for all combobox. You can do by following way.
string lastComboName=""; // define global variable
//common event handler for all combobox
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var cmb = (ComboBox)sender;
lastComboName = cmb.Name;
}
Hope that each comboBox having an unique name, then we can use those name to identify which one is the sender of event: Now consider the following code for this:
private void CboFirst_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox selctedComboBox = sender as ComboBox;
string ComboName = selctedComboBox.Name;
// Do something
}
Now tracking the last updated ComboBox, You can achieve this by keeping a blobal variable and update it in every trigger so Every time it holds the Latest value( the name of the combobox)

Get selected Item name from combo box

I have a combo box as shown in the code below. I would like to display the name of the selection in a message box when I select it. What I am trying is -
<dxb:BarEditItem.EditTemplate>
<DataTemplate>
<dxe:ComboBoxEdit x:Name="PART_Editor"
SelectedIndexChanged="OnSelectedIndexChanged" Name="comboBox">
<dxe:ComboBoxEdit.Items>
<system:String>Item1</system:String>
<system:String>Item2</system:String>
</dxe:ComboBoxEdit.Items>
</dxe:ComboBoxEdit>
</DataTemplate>
How can I add the code in the backend for getting the selected name inside a message box?
Do you mean to handle this on the SelectedIndexChanged event? If so you can get the combobox that triggered the event.
private void OnSelectedIndexChanged(object sender, RoutedEventArgs e)
{
ComboBox cb = (ComboBox)sender;
string selectedText = cb.SelectedText;
//Code to display the selectedText into a message box
}
I'm not sure what do you mean by the "name of the selection", so I'm assuming you want to get hold of the text that is displayed in the combo, which represents the selected item.
Once you have the combo itself in your hands:
private void OnSelectedIndexChanged(object sender, RoutedEventArgs e)
{
var combo = (ComboBoxEdit)sender;
(...)
}
you have several options. Most reliable one (in my opinion) would be to use combo.DisplayText property, which is a read-only property holding the actual text that should be displayed in the combo (with consideration of DisplayMember property, DisplayTextConverter property and CustomDisplayText event).
Another option (in your particular case) would be (string)combo.SelectedItem. Note though, that combo.SelectedItem returns the actual selected item and not it's text representation. The above is fine as long as items are of type string. Should they not be, you'll get an InvalidCastException. Also, it's possible that in that case what you get might not be what you see (as noted in previous paragraph there are several ways to modify the displayed text).
Yet another option is combo.Text, which takes into consideration DisplayMember, but not DisplayTextConverter nor CustomDisplayText.
EDIT
Turns out that at the time SelectedIndexChanged is raised, DisplayText property is not yet updated to reflect the newly selected item (which isn't especially surprising). To deal with that, you should "postpone" the retrieval of the DisplayText value. I'd personally go with something along these lines (using a Dispatcher associated with the combo):
private void OnSelectedIndexChanged(object sender, RoutedEventArgs e)
{
var combo = (ComboBoxEdit)sender;
combo.Dispatcher.BeginInvoke(new Action(() =>
{
var text = combo.DisplayText;
(...)
}));
}
just type comboboxName.Text and you will get the selected item of combobox

DragDropManager How to prevent from adding incoming element to list?

Currently my page consist of two grid side by side, each of the grid binding a list, says GridA binding ListA and GridB binding ListB.
Both of the grid implemented Telerik DragDropManager. In most cases everything works fine, user can simply drag element from GridA and drop on GridB and both ListA and ListB will reflect accordingly.
Now I'm trying to make a checking on GridB so that whenever user drag an element from GridA, if this element existed in GridB, the element won't be added.
I noticed I can implement a drop function at GridB as below:
<telerik:RadGridView
ItemSource="{Binding ListB}"
DataContext="{Binding [someViewModel]}"
Drop="abc_Drop"
DataLoaded="abc_DataLoaded"
x:Name="GridB">
And below will be my drop function:
private void abc_Drop(object sender, System.Windows.DragEventArgs e)
{
var selectedItem = (T)GridA.SelectedItem;
List<T> x = someViewModel.ListB;
}
In order to investigate, I put a breakpoint on abc_Drop method. What I found is that, while I execute abc_Drop method, someViewMode.ListB.Count() still return 0 but once it finish, someViewModel.ListB.Count() return 1. Hence my question, where should I do the checking and prevent element added into the list conditionally? What will be executed right after drop method?
I've found the answer myself.
private void abc_Drop(object sender, System.Windows.DragEventArgs e){
e.Handled = true;
var selectedItem = (T)GridA.SelectedItem;
if( /*condition*/ ){
ListB.Add(selectedItem);
}
GridB.Rebind();
}
By using e.Handled = true, it halted the operation and I can now implement my own logic into it

Dynamically get textbox's name

private void txt_f_name_TextChanged(object sender, TextChangedEventArgs e)
{
string textbox_name_1,textbox_name_2;
TextBox textbox_1 = (TextBox)e.Source;
textbox_name1= textbox_1.Text;
TextBox textbox_2 = (TextBox)e.OriginalSource;
textbox_name_2;= textbox_2.Text;
}
now both textbox_name_1 and textbox_name_2 are getting same result.
if i try to get another thing like text,with etc... these are also getting the same result....
but i think there may be some difference.
so,i want to know the major difference between e.source and e.OriginalSource.
There are cases source and original source differ.
Common cases where the source may be adjusted include content elements
inside a content model for a control (the contents of a list item, for
instance, will report the list item element as the Source and the
actual element within the list item will be the OriginalSource.
ref from MSDN:
i'm not sure what you try to do with your code. to check source and original source text property do like below, and you can do the same thing by adding list view with items having text box.
private void txt_f_name_TextChanged(object sender, TextChangedEventArgs e)
{
string textbox_name_1,textbox_name_2;
TextBox textbox_1 = (TextBox)e.Source;
textbox_name1= textbox_1.Text;
TextBox textbox_2 = (TextBox)e.OriginalSource;
textbox_name_2 = textbox_2.Text;
}
From the documentation
This originalsource property acquires its value once, before the class event handlers or any instance handlers are invoked, and is never adjusted past this point.
With routed events other events may have fired before your handler.
[OriginalSourece][1]
http://msdn.microsoft.com/en-us/library/system.windows.routedeventargs.originalsource.aspx

Categories