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;
}
Related
Is there a way to get OnItemRightTapped event on ListView or GridView that works exactly like ItemClick, except obviously react only on right tap?
You can add an event handler for mouse down and then determine the click source in the code:
private void listView_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Right)
{
// Do what u need to do here
}
else
e.Handled = true;
}
I have a standard Silverlight DataGrid with the RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected
I tried setting this property both in the XAML as well as in the parent control's Loaded event.
In the parent's Loaded event I'm setting the itemsource of the grid, then manually setting the selected index to 0.
This does NOT fire the RowDetailsVisibilityChanged event.
However, once I change the selection by clicking a new row, it will fire.
I need to access that first selection's row's "DetailElement" to populate a control within it with data. However the only way I know how to get that DetailElement is in the RowDetailsVisibilityChanged event.
Here's my code:
void ViewAssociationUserControl_Loaded(object sender, RoutedEventArgs e)
{
viewAssociationsDataGrid.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
viewAssociationsDataGrid.ItemSource = myData;
viewAssociationsDataGrid.SelectedIndex = 0;
}
private void viewAssociationsDataGrid_RowDetailsVisibilityChanged(object sender, System.Windows.Controls.DataGridRowDetailsEventArgs e)
{
if (viewAssociationsDataGrid.RowDetailsVisibilityMode == DataGridRowDetailsVisibilityMode.VisibleWhenSelected
&& e.Row.DetailsVisibility == System.Windows.Visibility.Visible)
{
Grid detailElement = e.DetailsElement as Grid;
if (detailElement != null)
{
ListBox assocControl = detailElement.FindName("oneToManyGridPanel") as ListBox;
UpdateOneToManyPanel(assocControl);
}
}
}
I couldn't figure out a way to cleanly handle this scenario so I ended up hi-jacking the initial "selection changed" occurrence and that first time, manually fire the visibility changed event myself:
private void viewAssociationsDataGrid_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (!initialTriggerFired) //manually fire the visibility the first time
{
initialTriggerFired = true;
DataGrid dataGrid = sender as DataGrid;
int selectedIndex = dataGrid.SelectedIndex;
if (selectedIndex > -1)
{
DataGridColumn column = dataGrid.Columns[0];
FrameworkElement fe = column.GetCellContent(dataGrid.SelectedItem);
DataGridRow row = fe.GetAncestorOfType<DataGridRow>();
if (row != null)
{
row.DetailsVisibility = System.Windows.Visibility.Collapsed;
row.DetailsVisibility = System.Windows.Visibility.Visible;
}
}
}
}
The problem is that your datagrid defaults the selected index to 0. Simply setting viewAssociationsDataGrid.SelectedIndex = -1 in your ViewAssociationUserControl_Loaded event handler will make it so that the selection change will register when the first row is initially selected.
A ListBox and a ContextMenu are created dynamicaly. The ListBox has some items.
How do I know the ListBoxItem Text that right mouse button clicked on?
private void Init2()
{
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItemOpen = new MenuItem();
menuItemOpen.Click += new RoutedEventHandler(menuItemOpen_Click);
contextMenu.Items.Add(menuItemOpen);
listBox1.ContextMenu = contextMenu;
}
void menuItemOpen_Click(object sender, RoutedEventArgs e)
{
//How do I know the listItem text that right mouse button clicked on?
}
When you right click, you actually also select. So that means you can just do:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
string selectedListBoxItemText = ((ListBoxItem)listBox1.SelectedItem).Content.ToString());
// do your thing
}
I have a Textbox withing the ControlTemplate of a MenuItem, which is inside a ContextMenu. The Textbox works well and I can type in it properly. But if I move the mouse over any of the other menu items in the context menu, they claim focus and I lose focus from the textbox. At this point I have to click back into the textbox to continue typing.
Is there a pattern or accepted method of resolving this issue?
Thanks
If you want to take back focus, you can type as below.
textBox.CaptureMouse();
textBox.ReleaseMouseCapture();
I think it can catch focus to textbox.
Well after trying a few different things, I got something to work:
For all other menu items that can capture focus (on mouse enter), set e.Handled = true for the PriviewGoTKeyboardFocus event:
void menuItem_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = true;
}
One can do this automatically from a window base class by looping through all menu items in a context menu. This requires hijacking the tag for those menuitems in which you insert the textbox.
void contextMenu_Opened(object sender, RoutedEventArgs e)
{
ContextMenu contextMenu = sender as ContextMenu;
foreach (FrameworkElement frameworkElement in contextMenu.Items)
{
if (frameworkElement is MenuItem)
{
MenuItem menuItem = (frameworkElement as MenuItem);
if (!(menuItem.Tag != null && menuItem.Tag.ToString() == "MaintainFocus"))
menuItem.PreviewGotKeyboardFocus += new KeyboardFocusChangedEventHandler(menuItem_PreviewGotKeyboardFocus);
}
}
}
void contextMenu_Closed(object sender, RoutedEventArgs e)
{
ContextMenu contextMenu = sender as ContextMenu;
foreach (FrameworkElement frameworkElement in contextMenu.Items)
{
if (frameworkElement is MenuItem)
{
MenuItem menuItem = (frameworkElement as MenuItem);
if (!(menuItem.Tag != null && menuItem.Tag.ToString() == "MaintainFocus"))
menuItem.PreviewGotKeyboardFocus -= menuItem_PreviewGotKeyboardFocus;
}
}
}
I have a DataGridView where SelectionMode=FullRowSelect and MultiSelect=False.
When a user clicks on a row it is selected as expected. However, clicking on the same row again does not deselect the row.
How can the row selection be made to toggle between selected and unselected?
As far as I know there is no out of the box functionality that will do this.
I managed to get the effect you are asking for with the following code:
public partial class Form1 : Form
{
private bool selectionChanged;
public Form1()
{
InitializeComponent();
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (!selectionChanged)
{
dataGridView1.ClearSelection();
selectionChanged = true;
}
else
{
selectionChanged = false;
}
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
selectionChanged = true;
}
}
That uses the dataGridView's SelectionChanged and CellClick events, along with a class level variable holding the state of the selection.