wpf get screen position of selected item in listview - wpf

In the mouseup event for a listview, how do I get the screen position of a selected item? I can get the screen position of the listview itself (.pointtoscreen) but can't find a way to determine the screen position of a selected item.
I've reviewed other SO articles but didn't find anything specific to items in the listview.

You can handle the ListBox.SelectionChanged event (or Selector.Selected). Then get the container of the selected item to calculate its coordinates:
partial class MainWindow : Window
{
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = sender as ListBox;
var selectedItemContainer = listBox.ItemContainerGenerator.ContainerFromItem(listBox.SelectedItem) as UIElement;
var pointOnSelectedItem = new Point(); // top-left corner
var pointOnScreen = selectedItemContainer.PointToScreen(pointOnSelectedItem);
var pointRelativeToWindow = selectedItemContainer.TranslatePoint(pointOnSelectedItem, this);
}
}

Related

WPF LIstview rows stay selected when button rows clicked

I have a button in a Listview column. In order for the entire row to select when the button is pressed, I use this code:
private void ButtonClick(object sender, RoutedEventArgs e)
{
ListViewItem selectedRow = GetAncestorOfType<ListViewItem>(sender as Button);
selectedRow.IsSelected = true;
}
public T GetAncestorOfType<T>(FrameworkElement child) where T : FrameworkElement
{
var parent = VisualTreeHelper.GetParent(child);
if (parent != null && !(parent is T))
return (T)GetAncestorOfType<T>((FrameworkElement)parent);
return (T)parent;
}
This all works great, but if I click the button in one row, then click the button in another row, both rows stay selected. I thought about going through and manually deselecting all rows every time a button is clicked, but I do need to be able to select multiple rows if ctrl is held down. Any suggestions?
Try using UnselectAll on the ListView before updating the selection:
private void ButtonClick(object sender, RoutedEventArgs e)
{
myListView.UnselectAll();
ListViewItem selectedRow = GetAncestorOfType<ListViewItem>(sender as Button);
selectedRow.IsSelected = true;
}

WPF DataGrid - maintain scroll position after refresh

Anyone knows how to maintain the vertical scroll position after the Refresh command?
My Datagrid receives binding from a List of objects.
Many thanks, and sorry for my english.
2 posible solutions :
1) Try to update the list instead of replacing it. it means adding new items and removing items you don't need.
2) you can save the state of the scroller before refreshing and then scroll programmly to the selected item.
WPF Toolkit: how to scroll datagrid to show selected item from code behind?
I had the same problem, here is what I did:
Find the ScrollViewer of your Datagrid/ListBox when it is leaded and add a ScrollChanged event:
var scrollViewer = FindScrollViewer(ListBoxOrders);
if (scrollViewer != null)
{
scrollViewer.ScrollChanged += scrollViewer_ScrollChanged;
}
//Here is the function to find the ScrollViewer:
private ScrollViewer FindScrollViewer(DependencyObject d)
{
if (d is ScrollViewer)
return d as ScrollViewer;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(d); i++)
{
var sw = FindScrollViewer(VisualTreeHelper.GetChild(d, i));
if (sw != null) return sw;
}
return null;
}
On scroll changed, store the vertical offset:
private double _verticalOffset;
private void scrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
var sv = (ScrollViewer)sender;
_verticalOffset = sv.VerticalOffset;
}
After refresh, scroll to the previous position:
scrollViewer?.ScrollToVerticalOffset(_verticalOffset);

How to add tab items to existing tab control from user Control in wpf

I have MainWindow and 2 user controls. In Main Window there is Tab Control which loads User Control if you click on button search in MainWindow. I could add tab items in main Window by this code.
private void search(object sender, RoutedEventArgs e)
{
tc.Visibility = Visibility.Visible; // It is hidden by default
TabItem tab = new TabItem();
tab.Header = "Поиск";
UCSearch c = new UCSearch(); // User Control 1
tab.Content = c;
tc.Items.Add(tab);
}
When User Control 1 is loaded in Tab item. There is Tetxbox and Button in User Control 1.I want to load User Control 2 when is clicking to Button. But I can not get access to Tab Control which is in Main Window from User Control 1. Please Give me direction. Where to dig?
You could use an Extension method to search the VisualTree for a Parent of type TabControl.
e.g.
Extension method:
public static class VisualTreeExtensions
{
public static T FindParent<T>(this DependencyObject child)
where T : DependencyObject
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
var parent = parentObject as T;
if (parent != null)
{
return parent;
}
else
{
return FindParent<T>(parentObject);
}
}
In your Button Handler:
private void Button_Click(object sender, RoutedEventArgs e)
{
var tabControl = (sender as Button).FindParent<TabControl>();
tabControl.Items.Add(new TabItem() { Header = "New"});
}
The better and more flexible (but also more complicated) solution would be to notify the participants (here: your Button fires some kind of message that it was clicked, others (your TabControl) listen and react on it (create a new Tab).
This can for example be done with a Mediator pattern or an EventAggregator.

WPF ListView MouseOver Item

For the wpf listview , in the Mouse Over event how do i get a reference to the item that the mouse cursor is on ?
Regards,
MadSeb
You have to use the MouseOver event from the listViewItem that the mouse is over, not the one from the listview itself.
public MainWindow() {
InitializeComponent();
ListView listView = new ListView();
ListViewItem listViewItem = new ListViewItem();
listViewItem.MouseMove += myMouseMoveEvent;
listView.Items.Add(listViewItem);
}
private void myMouseMoveEvent(object sender, MouseEventArgs e) {
ListViewItem item = (ListViewItem) sender;
// now you can handle the events with this item....
}

WPF ComboBox DropDown Placement

I have a ContentControl comprised from left to right of a Button, partition and a ComboBox. I want the ComboBox dropdown to line up with the left side of the control as opposed to the left side of the combobox. Can't seem to find docs on Relative placement, etc. Anyone dealt with this? TIA
I've done something similar before - I ended up deriving from ComboBox, getting the popup part of the control and using the CustomPopupPlacementCallback to position it. Something like this...
class MyComboBox : ComboBox
{
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var popup = (Popup)Template.FindName("PART_Popup", this);
popup.Placement = PlacementMode.Custom;
popup.CustomPopupPlacementCallback = placePopup;
}
private CustomPopupPlacement[] placePopup(Size popupSize, Size targetSize, Point offset)
{
var placements = new[] { new CustomPopupPlacement() };
placements[0].Point = // position the drop-down here!
return placements;
}
}

Resources