I have to set current row's ACTIVE field to 1 when user press Shift-Delete. I have setup KeyDown and CustomRowFilter events for GridView but I can't set the ACTIVE field to 1 with SetFocusedRowCellValue and SetRowCellValue methods.
private void gvMain_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Shift == true) && (e.KeyCode == Keys.Delete))
{
GridView gvTmp = sender as GridView;
//gvTmp.SetFocusedRowCellValue("ACTIVE", 1); //DOES NOTHING
//gvTmp.SetRowCellValue(gvTmp.FocusedRowHandle, "ACTIVE", 1); //DOES NOTHING
//gvMain.SetRowCellValue(gvMain.FocusedRowHandle, "ACTIVE", 1); //DOES NOTHING
//gvMain.SetFocusedRowCellValue("ACTIVE", 1); //DOES NOTHING
dtMain.Rows[gvTmp.GetDataSourceRowIndex(gvTmp.FocusedRowHandle)]["ACTIVE"] = 1; //OK
gvMain.RefreshData();
}
}
How can I set current row's ACTIVE field to 1 with GridView methods? I don't like to set values directly to datatable.
Related
I have overridden the CellPainting in a WinForms DataGridView to display a specific image in a cell depending on various factors.
To give you some more details, in the CellPainting I am redrawing the content of a DataGricViewCheckBoxColumn; I want to display a green tick or red cross instead of the default black tick.
To draw the image I use:
e.Graphics.DrawImage(image, new PointF(centreX - offsetX, centreY - offsetY));
It works fine, but my green tick/red cross is only displayed after the cell loses focus. Is there a way to make it show as soon as I have clicked it, just like the standard checkbox does?
Thanks
Handle the CellContentClick event to toggle the value (true/false) of the current cell. The CellContent of a DataGridViewCheckBoxColumn is the check box.
Assuming the DataGridViewCheckBoxColumn is the first column:
private void dgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex >= 0)
{
var s = sender as DataGridView;
var b = s[e.ColumnIndex, e.RowIndex].Value == null
? true
: (bool)s[e.ColumnIndex, e.RowIndex].Value;
s[e.ColumnIndex, e.RowIndex].Value = !b;
}
}
If you prefer to toggle the value by clicking anywhere on the cell (not over the check box only), handle the CellMouseClick instead:
private void dgv_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Left && e.ColumnIndex == 0 && e.RowIndex >= 0)
{
var s = sender as DataGridView;
var b = s[e.ColumnIndex, e.RowIndex].Value == null
? true
: (bool)s[e.ColumnIndex, e.RowIndex].Value;
s[e.ColumnIndex, e.RowIndex].Value = !b;
s.NotifyCurrentCellDirty(true);
}
}
Either way, the CellPainting event fires and the specified image is drawn as you click.
CellPainting example:
Bitmap bmp1 = Properties.Resources.GreenImage;
Bitmap bmp2 = Properties.Resources.RedImage;
private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex >= 0)
{
var s = sender as DataGridView;
e.Paint(e.CellBounds, DataGridViewPaintParts.Background
| DataGridViewPaintParts.Border
| DataGridViewPaintParts.SelectionBackground
| DataGridViewPaintParts.Focus
| DataGridViewPaintParts.ErrorIcon);
if (e.Value != null)
{
var r = new Rectangle((e.CellBounds.Width - 16) / 2 + e.CellBounds.X,
(e.CellBounds.Height - 16) / 2 + e.CellBounds.Y, 16, 16);
var b = (bool)e.Value;
e.Graphics.DrawImage(b ? bmp1 : bmp2, r);
}
e.Handled = true;
}
}
I have a GridView control of xtraGrid suite in a form.
When I open the form for first time it is AllowEdit = false. I want that when I press on add new row link(built in by control) to make editable this only new inserted row. I read that I should use ShowingEditor event but I don't know how.
I wrote this so far but this does not editable the row:
private void gridViewNote_ShowingEditor(object sender, System.ComponentModel.CancelEventArgs e)
{
//this is first tryout
//if (gridViewNote.IsNewItemRow(gridViewNote.FocusedRowHandle))// == gridViewNote.GetFocusedDataRow())
//{
// gridColumnStagione.OptionsColumn.AllowEdit = true;
//}
//second tryout
GridView view = sender as GridView;
SchedeMaterialiDaTaglioDS.SMTAGL_NOTERow currentRow = gridViewNote.GetFocusedDataRow() as SchedeMaterialiDaTaglioDS.SMTAGL_NOTERow;
SchedeMaterialiDaTaglioDS.SMTAGL_NOTEDataTable changesTable = dsSchMatTaglio.SMTAGL_NOTE.GetChanges() as SchedeMaterialiDaTaglioDS.SMTAGL_NOTEDataTable;
e.Cancel = !view.IsNewItemRow(view.FocusedRowHandle) &&
!changesTable.Contains(currentRow);// set.Inserts.Contains(order);
}
I hope I understood your question. A few simple ways of doing this:
Adding a repository item to each column and handle the ShowingEditor event, using e.Cancel if this is supposed to be read only.
Popping up a window/textboxes, letting the user insert values and add the row with values already inserted via code.
assigning two different repository items to the same column using gridView.CustomRowCellEdit event. like such:
RepositoryItemTextEdit rep = new RepositoryItemTextEdit();
RepositoryItemTextEdit noRep = new RepositoryItemTextEdit();
noRep.ReadOnly = true;
private void button1_Click(object sender, EventArgs e)
{
gridView1.AddNewRow();
justAddedName = true;
gridView1.RefreshData();
}
private void gridView1_CustomRowCellEdit(object sender, DevExpress.XtraGrid.Views.Grid.CustomRowCellEditEventArgs e)
{
if (e.Column == colname)
{
if (e.RowHandle == gridView1.RowCount - 1 && justAddedName)
{
e.RepositoryItem = rep;
}
else
{
e.RepositoryItem = noRep;
}
}
}
It's not complete, just a direction to explore.
Hope I helped.
I want to add a new row in my Silverlight DataGrid, when user try to go from LastRow to NextRow by Tab/Enter (as it last row, DataGrid loses focus). I can not use RowEditEnded event as it will fire even if i move to a PreviousRow from LastRow.
Can anyone help me achieve this?
If you look at DataGrid source code you can see that it traps key down event (f.i. to realize functionality like go to next row on enter pressed). As solution I propose to implement own grid inherited from DataGrid and add event which raised when user presses enter(or other) button. Own control:
public class MyDataGrid : DataGrid
{
public event EventHandler OnLastRowEnterPressed;
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (ItemsSource != null
&& ItemsSource.Cast<object>().Count() - 1 == SelectedIndex
&& e.Key == Key.Enter)
{
RaiseLastRowEnterPressed();
}
}
private void RaiseLastRowEnterPressed()
{
if (OnLastRowEnterPressed != null)
OnLastRowEnterPressed(this, EventArgs.Empty);
}
}
Using:
ObservableCollection<Foo> source = new ObservableCollection<Foo>()
{
new Foo(), new Foo(), new Foo(),
};
myDataGrid.OnLastRowEnterPressed += (s, e) => source.Add(new Foo());
myDataGrid.ItemsSource = source;
well vladimir, there seems to be no simple/direct way to add new row after last row exit. your solution will work but with consequences of event being raised in other key press events also. i have come up with the combination of events to get the solution.
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
addFlag = (e.Key == Key.Tab);
}
protected override void OnLostFocus(RoutedEventArgs e)
{
addFlag = (addFlag && true);
base.OnLostFocus(e);
}
protected override void OnRowEditEnded(DataGridRowEditEndedEventArgs e)
{
base.OnRowEditEnded(e);
addFlag = (addFlag && IsLastRowSelected);
if (addFlag)
AddItem();
addFlag = false;
}
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
addFlag = false;
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
addFlag = false;
}
private void AddItem()
{
if (RaiseAddEvent!= null)
{
this.Focus();
RaiseAddEvent(this, EventArgs.Empty);
this.UpdateLayout();
this.CurrentColumn = this.Columns[0];
this.BeginEdit();
}
}
You can use Routed events concept where trapping the Enter/Tab key , you can add new row to the data grid control.
I will expose by few steps. So lets start now..
1)Declare your event in constructor of this class.
this.DataGrid1.KeyDown += new KeyEventHandler(DataGrid1_KeyDown);
you also can it in XAML file.
...KeyDown="DataGrid1_KeyDown".....
2) Go to your keydown event & wrie the code.
var focusedElement = FocusManager.GetFocusedElement();
DataGrid detailsDataGrid = sender as DataGrid;
int dataGridrows = detailsDataGrid.ItemsSource.OfType<object>().Count();
if (e.Key == Key.Tab && (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
return;
if (e.Key == Key.Tab)
try
{
detailsDataGrid.SelectedIndex = row.GetIndex();
{
itemMaster.TransactionChilds.Add(transactionChild);
detailsDataGrid.SelectedItem = transactionChild;
}
}
3) Now code line by line..
DataGridRow row = DataGridRow.GetRowContainingElement(focusedElement as FrameworkElement);
DataGridColumn column = DataGridColumn.GetColumnContainingElement(focusedElement as FrameworkElement);
TransactionMaster itemMaster = this.DataFormVoucher.CurrentItem as TransactionMaster;
decimal serialNumber = 0;
if (buttonPress == "Modify")
if (dataGridrows - 1 == detailsDataGrid.SelectedIndex && column.DisplayIndex == 5)
TransactionChild transactionChild = new TransactionChild()"[None]",DateTime.Now.Date,catch (Exception ex)Console.WriteLine(ex.Message);
.DataGridChild.KeyDown += new KeyEventHandler(DataGridChild_KeyDown);
3) Now understand the code line by line
i) first 3 lines are used to take which row of a datagrid is selected.
ii)When new row will add in this case i have used Tab key you can also change this.Another things is if an user predd Tab+Shift then it will go through (default as control focus).
iii) then check is it last row & last column of this grid, if yes then add new row or else.
iv) to add a blank new row just pass your object (EDMX Model Table)
I have a Winforms DataGridView in my application.
I've two checkbox columns along with 5 other columns from the database. These two checkbox columns are added usng DataGridViewCheckBoxColumn.
When the user clicks on the 2nd checkbox, I need to show a message to the user if the first checkbox is not checked for that row.
How do I go about this?
I tried this,but the cell value is coming as null.
What am i doing wrong?
private void dgTest_CellClick(System.Object sender, DataGridViewCellEventArgs e)
{
DataGridViewCheckBoxCell officialCbCell = row.Cells[1] as DataGridViewCheckBoxCell;
DataGridViewCheckBoxCell includeCbCell = row.Cells[0] as DataGridViewCheckBoxCell;
if (officialCbCell != null)
{
if (officialCbCell.Value != null && (bool)officialCbCell.Value == true)
{
if (includeCbCell != null && (bool)includeCbCell.Value == false)
{
MessageBox.Show("INVALID");
}
}
}
}
Thanks.
You can try using the CellValueChanged event of the grid
void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0)
{
bool isChecked = (Boolean) dataGridView1[0, e.RowIndex].FormattedValue;
if (isChecked)
dataGridView1[1, e.RowIndex].Value = true;
}
}
if checked then you can set the other column as also checked or any other validation
CellContentClick event and cell.EditingCellFormattedValue property are also useful if you just un/clicked the cell.
I want to enable the user to highlight a row on the WPF DataGrid and press delete key to delete the row.
the functionality is already built into the UI of the grid, so to the user, the row disappears
I currently handle this on the SelectionChanged event (code below)
I loop through all the "e.RemovedItems" and delete them with LINQ
Problem is: even when you simply select a row and move off of it, selection change is fired and that row is in e.RemovedItems (which is odd, why would simply selecting something put it in a RemovedItems container?).
So I am looking for a DeleteKeyPressed event so I can simply handle it. What is that event called?
I am using the March 2009 toolkit.
XAML:
<Grid DockPanel.Dock="Bottom">
<toolkit:DataGrid x:Name="TheDataGrid"
SelectionChanged="TheDataGrid_SelectionChanged"
AutoGenerateColumns="True"
RowEditEnding="TheDataGrid_RowEditEnding"/>
code-behind:
private void TheDataGrid_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count > 0)
{
Message.Text = "The following were removed: ";
foreach (object obj in e.RemovedItems)
{
Customer customer = obj as Customer;
Message.Text += customer.ContactName + ",";
_db.Order_Details.DeleteAllOnSubmit(
customer.Orders.SelectMany(o => o.Order_Details));
_db.Orders.DeleteAllOnSubmit(customer.Orders);
_db.Customers.DeleteOnSubmit(customer);
}
}
try
{
_db.SubmitChanges();
}
catch (Exception ex)
{
Message.Text = ex.Message;
}
}
ANSWER:
Thanks lnferis, that was exactly what I was looking for, here is my finished delete handling event for the datagrid, note the KeyDown event doesn't fire for some reason.
XAML:
<toolkit:DataGrid x:Name="TheDataGrid"
KeyDown="TheDataGrid_KeyDown"
PreviewKeyDown="TheDataGrid_PreviewKeyDown"
AutoGenerateColumns="True"
RowEditEnding="TheDataGrid_RowEditEnding"/>
code-behind
private void TheDataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
var grid = (DataGrid)sender;
if (grid.SelectedItems.Count > 0)
{
string checkMessage = "The following will be removed: ";
foreach (var row in grid.SelectedItems)
{
Customer customer = row as Customer;
checkMessage += customer.ContactName + ",";
}
checkMessage = Regex.Replace(checkMessage, ",$", "");
var result = MessageBox.Show(checkMessage, "Delete", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
foreach (var row in grid.SelectedItems)
{
Customer customer = row as Customer;
_db.Order_Details.DeleteAllOnSubmit(
customer.Orders.SelectMany(o => o.Order_Details));
_db.Orders.DeleteAllOnSubmit(customer.Orders);
_db.Customers.DeleteOnSubmit(customer);
}
_db.SubmitChanges();
}
else
{
foreach (var row in grid.SelectedItems)
{
Customer customer = row as Customer;
LoadData();
_db.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, customer); //TODO: this doesn't refresh the datagrid like the other instance in this code
}
}
}
}
}
private void TheDataGrid_KeyDown(object sender, KeyEventArgs e)
{
Console.WriteLine("never gets here for some reason");
}
The RemovedItems items reflects the items removed from the selection, and not from the grid.
Handle the PreviewKeyDown event, and use the SelectedItems property to delete the selected rows there:
private void PreviewKeyDownHandler(object sender, KeyEventArgs e) {
var grid = (DataGrid)sender;
if ( Key.Delete == e.Key ) {
foreach (var row in grid.SelectedItems) {
... // perform linq stuff to delete here
}
}
}
XAML
<DataGrid ItemsSource="{Binding}" CommandManager.PreviewCanExecute="Grid_PreviewCanExecute" />
Code behind
private void Grid_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
DataGrid grid = (DataGrid)sender;
if (e.Command == DataGrid.DeleteCommand)
{
if (MessageBox.Show(String.Format("Would you like to delete {0}", (grid.SelectedItem as Person).FirstName), "Confirm Delete", MessageBoxButton.OKCancel) != MessageBoxResult.OK)
e.Handled = true;
}
}
What are you binding your DataGrid to?
Ideally, you should react to CollectionChanged events on the collection you are binding to. That way, your logic (deletion of removed items) will be separated from your UI.
You can build an Observable collection containing your objects and bind it to ItemsSource just for that purpose if the original collection does not have the necessary events.
It might not suit your specific setup, but that's how I usually do it.
Please follow the below code. I have succeeded with the below code.
Please let me know if changes are required.
private void grdEmployee_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Device.Target.GetType().Name == "DataGridCell")
{
if (e.Key == Key.Delete)
{
MessageBoxResult res = MessageBox.Show("Are you sure want to delete?", "Confirmation!", MessageBoxButton.YesNo,MessageBoxImage.Question);
e.Handled = (res == MessageBoxResult.No);
}
}
}
A little late to the party, but to get Inferis answer working:
Dim isEditing = False
AddHandler dg.BeginningEdit, Sub() isEditing = True
AddHandler dg.RowEditEnding, Sub() isEditing = False
AddHandler dg.PreviewKeyDown, Sub(obj, ev)
If e.Key = Key.Delete AndAlso Not isEditing Then ...
This fixes epalms comment: "if you're editing a cell and use the delete key to remove some characters in the cell, you'll end up deleting the whole row"
The cleanest solution is to use PreviewCanExecute like answered by flux, this is a completed solution to make it a bit more clear for anybody that overlooked his answer like I did:
private void Grid_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (e.Command == DataGrid.DeleteCommand)
{
if (MessageBox.Show($"Delete something from something else?", "Confirm removal of something", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
// Do what ever needs to be done when someone deletes the row
}
else
{
e.Handled = true;
// Handled means.. no worries, I took care of it.. and it will not delete the row
}
}
}
No need to hook on to CommandManager.Executed after this.
You want to handle the KeyUp or KeyDown event and check the pressed Key for Delete.
private void OnKeyDown(object sender, KeyEventArgs e) {
if ( Key.Delete == e.Key ) {
// Delete pressed
}
}