I have a grid which contains 2 rows and 2 columns. Each cell hosting a windows forms host control. I want to capture the selected cell when the user clicks on any of the cell. I have searched and found that there is no 'Click' event but I can make use of 'MouseDown' event with similar results. But now I am stuck because you would think there must be an easier way like 'GetCurentRow' and 'GetCurrentColumn' to capture the selected cell but there isn't.
What I want further to do is to get the child element in that particular cell of the grid.
I tried the following code but no matter which cell I click, I always get 0 for the row and column:
void InnerGridToContainWindowsFormsHost_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var element = (UIElement)e.Source;
int c = Grid.GetColumn(element);
int r = Grid.GetRow(element);
}
Is there any way to get the selected/clicked cell details or the children inside the cell?
I think that you may be going down the wrong route here... if you just want to know what control was clicked on, try using the VisualTreeHelper.HitTest method. You can find information on the VisualTreeHelper.HitTest Method page on MSDN. Basically, you would do something like:
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Get the position of the mouse pointer relative to the grid
Point clickPoint = e.GetPosition(grid);
HitTestResult result = VisualTreeHelper.HitTest(grid, clickPoint);
if (result != null)
{
// Do something here
}
}
You may also need some kind of basic recursive function to drill down through the Visual objects until you get to the one you want.
Related
Im trying to add a UserControl in WPF to a grid, but it doesnt show up when im trying to add via MyGrid.Children.Add(UserControl). So i tried to display the number of childs of my grid and it says 1 after adding the usercontrol. (MyGrid.Children.Clear() doesn't work too. After clearing the grid it says that there are 0 childs left but there are still some UiElements when im compiling my program.)
This problem appears only in 1 function. In an other function (the same class) i can easily add childs to the same grid (myGrid).
My code:
private void AddDateOnClick(object sender, MouseButtonEventArgs e)
{
MyGrid.Children.Clear();
UserControlAddDate ucad = new UserControlAddDate();
MyGrid.Children.Add(ucad);
MessageBox.Show(MyGrid.Children.Count.ToString()); //Only to test if there are some childs
}
When i try to clear this grid in a other function (same class) it clears the grid. Only clearing in this function is a problem. Im not understanding why???
What is this UserControlAddDate? Maybe it is not initialized. That’s why it’s not getting added to the grid..
In that place try to add a textbox to the grid and check if it’s working. If it’s working then it’s the problem with your code.
As mentioned by Ed Plunkett, please try to use templates and databinding. It's the best way to work with WPF.
Try this anyway.
private void AddDateOnClick(object sender, MouseButtonEventArgs e)
{
MyGrid.Children.Clear();
TextBox ucad = new TextBox();
ucad.Text = “TEST”;
MyGrid.Children.Add(ucad);
MessageBox.Show(MyGrid.Children.Count.ToString()); //Only to test if there are some childs
}
In project there is a DataGridView.
I have a little bit of code that I which displays information based on
the cell that was clicked.
My problem is how to detect if the user clicked on a column or row
header (anything other than a cell).
All this is tied to the 'dataGridView1_CellMouseDown' method, and I'm using
the HitTest to attempt to detect what the user clicked, but all I'm
getting is 'TopLeftHeader' when the user clicks a cell and 'None'
everywhere else and the Row index always comes as -1
Using the CellMouseDown event gives you coordinates relative to the cell that was clicked.
Use the control's MouseDown event instead, which will give you control-based coordinates.
See the example on MSDN.
You can still use the CellMouseDown event handler. In fact i find it a bit cleaner because with MouseDown event, you have to create a HitTest to get the selected row.
The following code is equivalent:
private void dgv_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
// If right-click
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
// Get selected row
var selectedRow = dgvBatches.Rows[e.RowIndex];
}
}
private void dgv_MouseDown(object sender, MouseEventArgs e)
{
// If right-click
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
// Get the selected row/column
DataGridView.HitTestInfo info = dgvBatches.HitTest(e.X, e.Y);
// Get selected row
var selectedRow = dgvBatches.Rows[info.RowIndex];
}
}
I am trying something simple but struggling to get a simple solution, just not seeing it hehe.
I have a number: “150” witch can be split in any number of segments when the user enters the segment amount in a textbox; a items control gets populated with textboxes showing the segment sizes. This works.
I want to be able to edit a segment size and then calculate the remaining sizes left to show on the other segment textboxes, but cant figure out how to do it. If someone can just point me in a direction tanks.
To show what I mean i have included a link to the project vs2010 here (49kb)
I'm unsure whether you're having trouble editing an existing segment size or whether its the re-calculation that you're having trouble with.
But one method might be to subscribe to the KeyDown event on the textbox, then check for the return key. then you could recalculate the segments , iterate the collection and update each item with the new segment.
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
TextBox textbox = sender as TextBox;
int newSegments;
if (int.TryParse(textbox.Text, out newSegments))
{
//recalculate the segments
//iterate the collection
//update the segments
}
}
}
I have a silverlight control in which i am dynamically creating shapes on button click
These shapes are draggable across the form. Now i want to get top and left postion of a control on dragging (mousemove). Please help
Taking a look at your question history I can think of two approaches. I suspect that the shape is simply being placed on a Canvas and the MouseMove of which you speak refers to an event handler you've attached to the Canvas. On that basis then.
void Canvas_MouseMove(object sender, MouseEventArgs e)
{
Type currentType = e.OriginalSource.GetType();
// Make decisions based on value of currentType here
DependencyObject source = (DependencyObject)e.OriginalSource;
Point p = new Point(Canvas.GetLeft(source), Canvas.GetTop(source));
}
The more general solution is to use the TransformToVisual approach. Something like:-
var transform = ((UIElement)e.OriginalSource).TransformToVisual(MyCanvas);
Point p = transform.Transform(Point(0,0));
I want to be able to pick a specific cell in a Silverlight 3.0 DataGrid and put it into edit mode. I can use the VisualTreeManager to locate the cell. How do I switch to edit mode?
Each DataGridCell looks like this in the VisualTreeManager:
System.Windows.Controls.DataGridCell
System.Windows.Controls.Grid
System.Windows.Shapes.Rectangle
System.Windows.Controls.ContentPresenter
System.Windows.Controls.TextBlock
System.Windows.Shapes.Rectangle
System.Windows.Shapes.Rectangle
with the TextBlock containing the text I want to edit.
Update
Following #AnthonyWJones' suggestion, here's how I tried to do this using BeginEdit().
I wanted to keep it simple so I thought I'd pick a column in the first row. Even that proved beyond my SL knowledge! In the end, I get the first row by creating a field called firstRow to hold it:
private DataGridRow firstRow;
added a LoadingRow handler to the DataGrid:
LoadingRow="computersDataGrid_LoadingRow"
and
private void computersDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
if (this.firstRow == null)
this.firstRow = e.Row;
}
and then adding a button to the panel to trigger the edit:
private void Button_Click(object sender, RoutedEventArgs e)
{
this.dataGrid.SelectedItem = this.firstRow;
this.dataGrid.CurrentColumn = this.dataGrid.Columns[4];
this.dataGrid.BeginEdit();
}
I click the button and the correct cell is selected but it doesn't go into edit on the cell. It takes a manual click to achieve that.
I'm not sure why you need to find the DataGridCell using VisualTreeManager nor do I know currently how you would properly start editing . You may get away with simply setting the cell's visual state to editing.
VisualStateManager.GoToState(myDataGridCell, "Editing", true);
I'm not sure how the grid behaves when you do something like the above. You may find things goe a bit pearshaped if you need DataGrid to help you revert changes to a row.
The "standard" approach would be to set the DataGrid SelectedItem property to the item represented by the row, set the CurrrentColum property to the DataGridColumn object that represents to the column in which the cell is found. Then call the BeginEdit method.
I am not able to understand your problem properly, but I had a similar problem
I wanted to make only few of the Grid Cells editable and rest were not. Instead of creating a logic and assigning ReadOnly as true/ false, I did the simple thing.
Mark the whole Grid's cells are writable, IsReadOnly as false
Set the event PreparingCellForEdit and send a callback
When you double click on a cell, it gets in the edit mode
Check whether this cell you want to be editable
If it is allowed to be edited, go ahead
If that cell is ReadOnly, then call CancelEdit
The sample code goes like
namespace foo
{
public class foobar
{
public foobar()
{
sampleGrid = new DataGrid();
sampleGrid.IsReadOnly = false;
sampleGrid.PreparingCellForEdit += new EventHandler<DataGridPreparingCellForEditEventArgs>(sampleGrid_PreparingCellForEdit);
}
void sampleGrid_PreparingCellForEdit(object sender, DataGridsampleGrid_PreparingCellForEditEventArgs e)
{
if (sampleGrid.SelectedItem != null)
{
bool isWritableField = CheckIfWritable()
if (isWritableField == false)
{
sampleGrid.CancelEdit();
}
// continue with your logic
}
}
private DataGrid sampleGrid;
}
}