I have three datagrids: MasterDatagrid, DetailDatagrid, AssocationDatagrid.
Bascially, if i select one row in one of the grid, i press 'delete' key to remove a row from that grid.
private void MasterDataGrid_IsMouseCapturedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
??
}
how can i replicate this function in my delete button ? how can i detect where my mouse focus is? and how to detect the right datagrid i am in?
Many thanks
One way to do it:
You can define a focus scope in the xaml on your page or user control using FocusManager.IsFocusScope.
Then on the OnClicked event of your button you can get the focused element using FocusManager.GetFocusedElement() method.
From there you can get the required item using SelectedItem(s) property and delete it.
Related
I have a DataGrid implemented in an MVVM/Prism application. The DataGrid supports Cut/Copy/Paste/Delete through a context menu and keyboard gestures.
I find that when a row is deleted/cut the entire DataGrid loses focus and keyboard focus moves to the last focused control.
Is there anyway to prevent this?
After removing a row I may want to re-paste into the DataGrid. Furthermore if the grid is empty there is no way at all for it to get keyboard focus. Clicking an empty grid does not give it focus.
Here is a similar question, but it doesn't solve the issue for me:
DataGrid Looses Focus When Delete Key is Pressed
You could set the DataGrids Focus in the PreviewKeyDown-Event
private void TheDataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
var grid = (DataGrid)sender;
FocusManager.SetFocusedElement(Window.GetWindow(grid), grid); //not tested
}
}
If you dont want to put code in code-behind use AttachedProperties in combination with the DependencyPropertyChanged-Event.
How to set set focus.
A dirty solution might be to handle the LostFocus event exposed by DataGrid and set focus on the control.
It arguably marginally infringes on the MVVM pattern i.e keeping the view dumb as hell, but it's still view code.
I have a hyperlink button colum in silverlight telerik radgridview, as a cell template.
I am using MVVM.
When i click on the hyperlink button, how can i get its row's values(atleast in the code behind)..?
Thanks in advance..
You need to use the ParentOfType extension method to get hold of the row containing the button.
Once you have the row you can cast the item type to your viewmodel and access the properties of it.
Make sure you have a using statement for the extension method:
using Telerik.Windows.Controls;
private void Button_Click(object sender, RoutedEventArgs e)
{
var parent = (sender as Button).ParentOfType<GridViewRow>();
var rowVM = parent.Item as YourVmClass;
}
If you are using MVVM you can also use the EventToCommandBehavior.
This allows you to execute all events as commands. You can then handle the command in your viewmodel.
In Silverlight 5, I have a DataGrid with a ContextMenuService.ContextMenu. If you click a row to select, then right click, you just check the grid.selecteditem for context. However, if you right click a row without selecting it, you don't have that row's context when the menu opens. How do you get the DataContext row of the grid that was right clicked on when the context menu opens? The right click on the grid seems to be an option, but it is intercepted for the contextmenu and does not fire unless a contextmenu is already open/in focus.
I have found tons of examples of getting around the original issue with Silverlight 4 and detecting the rown on right click. However, the contextmenu now intercepts the rigth click of the grid, so those no logner work. I also found posts on 'bugs' with the initial relase of the ContextMenu. All these posts/blogs are making it hard to find a current answer or solution.
yeah it seems like Silverlight 5 has changed something that breaks the old tricks.
We've been doing this: add row enters on row load handler. EG:
private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.MouseEnter += new MouseEventHandler(Row_MouseEnter);
e.Row.MouseLeave += new MouseEventHandler(Row_MouseLeave);
}
void Row_MouseEnter(object sender, MouseEventArgs e)
{
DataGridRow dgr = sender as DataGridRow;
IncidentGrid.SelectedItem = dgr.DataContext;
}
pretty ugly i know, but it's working.
Besides Roger's concerns of accuracy, I didn't want to wire up those events on every row because my grid is quite large, and I have to keep it lean.
I found a solution here...
https://mutelight.org/silverlight-datagrid-make-right-click-select-a-row
Apply just one event handler to the grid's MouseRightButtonDown event. The event args has the mouse position and you can use VisualTreeHelper to find which DataGridRow the mouse is over. Then that row's DataContext will have your SelectedItem.
I am experiencing some very strange mouse-event behaviour when working with Silverlights DataGrid:
What I want to do is simply call some method when the user left-clicks over my DataGrid. That shouldn't be much a problem, but ...
With
public void doLeftClick (object sender, MouseButtonEventArgs e) {
// some code
}
i am defining the EventHandler and with
myDataGrid.MouseLeftButtonDown += doLeftClick;
i am attaching it to the event.
The result of that is that the doLeftClick method only gets called when i left-click over one of the columns of my DataGrid!
When i am doing the exact same code as above only for the right-click instead of the left-click the EventHandler gets called everytime i right-click over my DataGrid regardless where the mouse cursor is, as long it is inside the boundaries of the control (which is what i actually need with the left-click and what's the behavior i would expect from this setting):
public void doRightClick (object sender, MouseButtonEventArgs e) {
// some code
}
myDatagrid.MouseRightButtonDown += doRightClick;
So what am i doing wrong ? What am i forgetting ?
I really would appreciate any help :)
Marc
The click events are not bubbled up. If a child control marks the event as handled it stops.
In this instance the left click is being eaten by the DataGrid cells (in order to select them and/or give focus to edit controls).
Right click is not used by the cells in the same way, so propagates up to the DataGrid control.
The column headers are nice enough to allow the left click to propagate.
I have a search screen with some textboxes and a Search button as the default. If I type in a textbox and I CLICK the button, everything's great. But if I press enter within a text box, the button command fires but the binding on whatever text box I was in does NOT fire and so my criteria doesn't make it to the view model to get filtered on.
I know one fix is to set the bindings on the text boxes to PropertyChanged, but this seems like way overkill. I might have logic in the viewmodel doing stuff and I don't want that to trigger on every single keystroke.
What I really want is a way for the button itself to either trigger a focus change or somehow trigger binding. Or to have the textbox trigger binding if focus is lost OR I press enter OR a command is executed from anywhere
One way to do this is with a BindingGroup.
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.bindinggroup.aspx
If your TextBox(es) and Button are both contained within a Grid (for example), you would add a BindingGroup like this:
<Grid>
<Grid.BindingGroup>
<BindingGroup Name="bindingGroup1"/>
</Grid.BindingGroup>
Then you could add a Click event handler to your button and call CommitEdit() on the BindingGroup (which the Button and TextBox inherit from the Grid):
private void button1_Click(object sender, RoutedEventArgs e)
{
(sender as FrameworkElement).BindingGroup.CommitEdit();
}
The Button.Click event fires before the CommandBinding, so any databound TextBox or any other databound controls within that BindingGroup should be updated before your view model command gets executed.
I've had the exact scenario you just mentioned. The trick I use is an attached behavior that sits on a control and listens for the PreviewKeyDown event. It checks if enter is being pressed. If so it forces the control to lose focus, thus causing the binding to fire before the command executes.
A simpler approach (rather than using a binding group) is to use the default button's click event to set the focus to itself. As this happens before the command is executed it means the ViewModel is updated in time.
private void button1_Click(object sender, RoutedEventArgs e)
{
(sender as Button).Focus()
}
And if you really hate code behind, you could always write an attached property...