How to retrieve index of ListViewItem currently being hovered over? - wpf

I've done some digging in trying to solve this, but haven't yet found a solution that works for me.
Basically I have an <ItemsControl> and in the <ItemsControl.ItemsTemplate> I have a <ListView> which displays a number of people's names. There will always be between 0 and 5 people's names listed.
What I want to do is have a tooltip popup with additional information relevant to the entity that is being hovered over. How do I get the index (or the content like the name) of the item I am currently hovering over though, to ensure that what the tooltip is displaying is for the correct person?!
I have a MouseEnter event on the listview which is triggered every time the mouse moves over an entity & in debug mode I can explore down into the sender details & can find the person's name that I want, but how do I get to it from code?
What I want is something like:
int index = sender.GetCurrentlyHoveredOverItem();
I don't want to overcomplicate this post by listing everything I've tried, but if you want any further info, please let me know.
Thanks in advance for your help!

As others have hinted at, but not explicitly said, the items in the ListView should implement the tooltip directly, using an ItemTemplate if needed, rather than at a global level.
<ListViewItem ToolTipService.ToolTip="Tooltip for this item" />

So you have a collection (ItemsControl) of lists (ListView) and you need the tooltip to be specific to a specific element within one of the internal lists, did i understand that correctly?
If so, why not create a ListView.ItemTemplate to take care of that?

If you are using MVVM…
Bind IsMouseOver to a property in the VM, like "CurrentlyHoveredPersonList". Use OneWayToSource.
Create another VM property called "HoveredPersonListViewModel" that contains all the details you need for your tooltip. When CurrentlyHoveredPersonList gets set, populate HoveredPersonListViewModel and raise a property change notification. You'll get an actual reference to the object, so you might not need the index, but if you do you can use IndexOf(object) to get it from the source list right there in the view-model.
Bind the tooltip's DataContext to HoveredPersonListViewModel and its constituent controls to the appropriate properties thereof.

Related

Dynamic Databinding in WPF

I am filling up a Stackpanel with Textboxes. Each textbox, Should display the Value Property of a Class i have written.
The number of Textboxes is always different so i can't create a databinding in the xaml file.
Are there tutorials, that show how can i archive my goal?
Edit: Thanks for the replies so far. After reading the articles i still not clear how to implement my Problem.
Here is what I'm trying to achieve:
I have an SQL Server DB and there a Table with an ID and a Value.
I now load all Values and IDs i want to display into my application. (number of loaded rows is always differnt).
I need to display a textbox for each row and display the value there and after the value is changed i write the value back to the database.
I don't know how I should query the data and than bind it to the textboxes.
I don't need an implementations, I am happy with every piece of advice I can get.
yes there are a number of tutorials out there. It sound like you are interested in datatemplating.
I would suggest looking Here on MSDN. A few tutorials on databinding in general may be useful DataBinding on MSDN
If your class, classValue, has a public property Value then just create a List and bind that to a ListBox with the item DisplayValuePath = Value. Repeater controls are used to bind to collections.

WPF Listbox Selection problem

I have a strange problem with a listbox. I added only the listbox and a button which adds items to the listbox. If I click an item in the listbox it seems to have some strange multi selection mode on or something... i recorded a short screen cast, see for your self:
http://www.youtube.com/watch?v=zV4424ipNEA
any ideas whats wrong?
That is a known issue, as all those strings are the same the selection gets confused because they all are essentially the same object. If you create two identical strings in .NET it does not necessarily create a new one but may reuse the first instance, i am not an expert on this though.
Either wrap the strings in a class (make them the Content of a ListBoxItem for example) or make sure the values are unique.

WPF - how to bind to source in different page?

Could anyone answer a really frustrating newbie question please?! I've been hunting for an answer for a few days & have found answers to similar questions posed, but nothing that exactly solves my issue.
I'm trying to bind a textbox to the currently selected item in a listview (which itself is bound to an Observablecollection of objects, not sure if this matters).
The listview is in RecentEntities.xaml & the textbox is in Relationship.xaml, both of which are positioned on the Main Window from within Maincontrol.xaml. So they're in the same namespace but they're in different pages so using ElementName doesn't work as this just seems to look within the current page.
The issue I'm having is when trying to define the source of the textbox binding in Relationship.xaml, how do I reference the selected listview item in RecentEntities.xaml? I wondered about using RelativeSource, but this seems to only let you navigate up the tree to an ancestor of the current control. Because of how MainControl is set up, I would need to travel up to the parent of the textbox, then to a sibling of the parent then down to a child of a child of it in order to get to the listview!
I've explored (possibly not in enough depth) other options like resources, data context, including header files and have read something about Merged Resource Dictionaries but to be honest the more possibilities I explore, the more confused I'm getting about what I need to be doing.
Is this really as complicated as it seems?! Any pointers or help would be brilliant, thanks for taking the time to answer :) I haven't posted on here before, so if you need any code snippets please let me know.
Can you create a ViewModel that both Views will use? Have the selected item in your listview bind to a property in the ViewModel and have the textbox bind to the same property. As long as both views reference the same instance of the viewmodel, it should work.
With two XAML files you will have to use the model or viewmodel (depending on your choice of architecture) for synchronization.
For the listview you can use the SelectedValue to bind to a property, use Mode=OneWayToSource for this binding since you just want to update the property, not change the selection in the listview itself.

.NET WinForm ListBox item displays old value untill reassigned to itself

I populate a ListBox control with my own objects redefining ToString(). The objects are displayed correctly when I just add those objects using listBox1.Add(myObject). However, if I later change something in this object, no changes are displayed in the listbox. Debugging reveals that an object inside listBox1.Items is indeed changed, but it is not reflected on a screen.
Interestingly enough, if I reassign a particular listbox item to itself (sounds a bit weird, doesn't it?), like:
listBox1.Items[0] = listBox1.Items[0]
this line will display a correct value on screen.
What is going on here? Does it have anything to do with threading?
Since you're using ToString of the object to provide the text of the list box item, the ListBox has no idea that the value has changed. What you should do instead is have the object implement INotifyPropertyChanged then expose a public property such as Name or Text and return what you normally would have returned from ToString().
Then set the DisplayMember of the ListBox to the name of the new property.
Make sure you are correctly raising the PropertyChanged event in the object and the ListBox should be able to automatically pick up the changes.
Edit: Adrian's edit reminded me that I do believe you'll need to use a BindingList as your data source in order for the property change notifications to be picked up. A quick scan in Reflector looks like ListBox on its own will not pick up the property changes mentioned above. But INotifyPropertyChanged + BindingList should.
The ToString() value of each item is cached when the listbox is first displayed. If an item in the listbox's Items collection then changes, the listbox does not notice and still uses the cached ToString() values for display. To force the listbox to update, either call RefreshItems() to refresh all items, or call RefreshItem(int) specifying the index of the item to refresh.
From the MSDN docs for RefreshItems():
Refreshes all ListBox items and retrieves new strings for them.
EDIT: It turns out that both of these methods are protected, so cannot be called externally. In trying to find a solution, I came across this SO question that this question is basically a duplicate of.
Have you tried calling Refresh() on the ListBox? I think the problem is that the ListBox does not know your object changed. The reason reassigning the the item works is because the ListBox will repaint itself when the collection changes.
you could invalidate the control, forcing a re-paint... perhaps..

How to display in each ListBoxItem textblocks with binding to a filelds of a different tables

Greetings to all and sorry for my English!
I have a ListBox, it's ItemsSource = myClientsList.DefaultView. The Items of ListBox have a template (ControlTemplate), that is defined in a in a separate resource file.
Every Item contains a little TextBlock's, Text -property of each have a binding to fields of my Object myClientsList.
I need to add in a this item template more TexBlock's and each of them must have binding to fields of another my class myOrdersList. - (So I wish to view on each line of ListBox information from different tables of my database - this is a question).
Problem in that that ListBox's ItemsSource have a link to object myClientsList and I cann't set myOrderList to ItemSource of same ListBox. So i must find a way to specify TextBlock.DataContext wich inside ControlTemplate or how it's possible to solve this problem in another way?
p.s. I'm a new in .Net and WPF and probably have a mistakes in my explanation - sorry for it.
It sounds like you have a DataGrid type of display and want to add more columns in order to display the order information for a given client. If this is the case, you are going to have to do a couple of things. First, you will need to create a composite object that stores information for both entities into a single object (so each row of your control has all the data it needs to display). Secondly, I would recommend using an actual DataGrid control to display rows instead of templating a ListBoxItem. The ListView with a GridView built into the framework isn't great, so I would recommend the WPFToolkit's DataGrid for a free option.
There are two issues here, if I've understood the question: how do you create a single collection containing both Clients and Orders, and how do you display Clients and Orders in different ways within the same ListBox?
Regarding the first, you can do this using a CompositeCollection.
Regarding the second, define two DataTemplates instead of a ControlTemplate. As the key of each DataTemplate, use the type of the object it is going to present e.g.
<DataTemplate x:Key="{x:Type local:Client}">
Alternatively, use ItemsControl.ItemTemplateSelector to explicitly point at different DataTemplates depending on the type of item. Ot if you really have to use ControlTemplates, check out ItemsControl.ItemContainerStyleSelector.

Resources