Make cells in a grid non-editable - c#

In my syncfusion grid, I have to make some series cells non-editable based on the type.
If the type is an 'XXX' then the cell is editable,
If the type is a 'YYY','ZZZ' then cell is non-editable
So here;'s what I did.
private void theGrid_CurrentCellChanging(object sender, System.ComponentModel.CancelEventArgs e)
{
fp_data_typ typ;
int nSeries = theData.GetNumSeries();
for (int i = 0; i < nSeries; i++)
{
typ = theData.CheckType(i);
if (!(typ == 'XXX'))
{
e.Cancel = true;
}
}
}
I am not sure if I should be using theGrid_CurrentCellChanging event or theGrid_CurrentCellStartEditing. Documentation is not very clear. Gives me a ton of events to handle cell edit.
The code earlier works in an incorrect way. It does not work if the grid has a combination of editable and non-editable series. i:e if it has both xxx)editable and 'yyy'(non-editable), it makes both non-editable.

I was able to get the column index of the current cell and from there set e.cancel to true/false. Instead of setting e.cancel for the whole grid once, I went for the cell being edited.

Below events will help you to achieve your requirement.
//Use this if you want to control the ReadOnly setting while loading itself
grid.QueryCellInfo += new GridQueryCellInfoEventHandler(grid_QueryCellInfo);
void grid_QueryCellInfo(object sender, GridQueryCellInfoEventArgs e)
{
if (e.Style.CellValue.Equals("YYY"))
{
e.Style.ReadOnly = true;
}
}
//Use this if you want to Validate while Editing
grid.CurrentCellValidating += new CurrentCellValidatingEventHandler(grid_CurrentCellValidating);
void grid_CurrentCellValidating(object sender, CurrentCellValidatingEventArgs e)
{
//Will deactive the cell and new value will be discarded
//e.NewValue = e.OldValue;
//To remain in Edit mode without committing the vlaue
e.Cancel = true;
}
Thanks,
Sivakumar

Related

how to remove or disable the extra column and row selection function?

I have grid view, and I have already disable the column auto width so I can manually set the size of column. after manually resize there's a extra blank column. and what I want is :
To disable the select row function when i click on outside of the column in Active, code and generate
Remove the extra column.
I already success fully hide the remaining column with this event or code
private void gridView1_CustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e)
{
if (e.Column == null)
{
e.Handled = true;
}
}
The thing is I still can click on the outside of the genre, and the row selection still follow where I click
Handle the GridView.MouseDown event in the following way:
private void gridView1_MouseDown(object sender, MouseEventArgs e) {
GridView view = (GridView)sender;
var hi = view.CalcHitInfo(e.Location);
Console.WriteLine(hi.HitTest);
if (hi.InRow && !hi.InRowCell)
DXMouseEventArgs.GetMouseArgs(e).Handled = true;
}

how to make particular column editable for copy in datagridview of devexpress in c#?

I have devexpress datagridview that have 10 columns with first column as Name which is non-editable but the user should be able to copy the cell content(Name).
private void gridViewBatches_ShowingEditor(object sender, System.ComponentModel.CancelEventArgs e)
{
GridView view = sender as GridView;
if (view.FocusedColumn.FieldName == "Batch No") //Editable true
{
e.Cancel = false;
} else //Other column editble false
{
e.Cancel = true;
}
}
One solution is to change ReadOnly or AllowEdit options of your columns.
Other solution is to use the ShowingEditor event of the view and disable cell editing via code using the event handler's e.Cancel parameter.
Here is the code snippet:
//Disable updating on the entire grid
uGrid1.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.False;
// Disable the first column in the first band
ultraGrid1.DisplayLayout.Bands[0].Columns[0].CellActivation = Activation.Disabled;
// Disable the first cell in the grid
uGrid1.Rows[0].Cells[0].Activation = Activation.Disabled;
ultraGrid1.DisplayLayout.Bands[0].Columns[0].CellActivation = Activation.Disabled;
Update :
Following solution works for Amol as confirmed in comments, including here for others benefit.
private void gridViewBatches_ShowingEditor(object sender, System.ComponentModel.CancelEventArgs e)
{
GridView view = sender as GridView;
if (view.FocusedColumn.FieldName == "Batch No") //Editable true
{
e.Cancel = false;
} else //Other column editble false
{
e.Cancel = true;
}
}

How to set the focus on the next/previous cell inside a DataGrid? Especially after calling grid.CommitEdit()?

I've a custom combobox template because of some binding stuff that won't work with the 'default' ComboBoxColumn.
To make it look 'nice' I've one template for the edit mode (a Combobox) and one for the 'normal' mode (a Label).
Now, because of that I've to commit the edit made to the combobox manually inside the CellEditEnding event
private bool changeCommitInProgress = false;
private void table_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditingElement is ContentPresenter && e.EditAction == DataGridEditAction.Commit)
{
if (!changeCommitInProgress)
{
changeCommitInProgress = true;
DataGrid grid = (DataGrid)sender;
grid.CommitEdit(DataGridEditingUnit.Row, false);
changeCommitInProgress = false;
}
}
}
The problem with this is, that it'll remove the focus from the entire datagrid. Just to be on the safe side, these are the only properties I changed on the datagrid (aside from the Name property and the ItemsSource):
grid.AutoGenerateColumns = false;
grid.IsSynchronizedWithCurrentItem = true;
grid.SelectionUnit = DataGridSelectionUnit.Cell;
This is a fun question. I have done similar with a nested DataList where I had to add a new row after last entry and focus on the first textbox of the newly generated row, maybe you can extrapolate my strategy to fit your situation?
protected void calcAvg(object sender, CommandEventArgs e)
{
int row = Convert.ToInt32(e.CommandArgument.ToString()) - 1;
DataListItem ActiveRow = dlMeasurements.Items[row];
// Snipped code doing stuff with current row
// Compare how many rows completed to number of rows requested
if (!(row + 1 == Convert.ToInt32(txtSample.Text)))
{
// Create new row
DataRow drNew = nextMeas.Tables[0].NewRow();
nextMeas.Tables[0].Rows.Add(drNew);
// Change item index and rebind
dlMeasurements.EditItemIndex = row + 1;
dlMeasurements.DataSource = nextMeas.Tables[0];
dlMeasurements.DataBind();
//Set focus with the Script Manager
smInspection.SetFocus((TextBox)(dlMeasurements.Items[row + 1].FindControl("txtRead1")));
}
else
{
// Otherwise close the measurements and show exit button
dlMeasurements.EditItemIndex = -1;
dlMeasurements.DataSource = nextMeas.Tables[0];
dlMeasurements.DataBind();
btnSaveAndPrint.Visible = true;
}
}
}

Can I make row cell value readOnly on XtraGrid just for one row?

How can I make a specific row cell readonly(not editable) on XtraGrid? For example just for row[0] but not all rows.
You can use the GridView.CustomRowCellEdit event:
//...
var repositoryItemTextEditReadOnly = new DevExpress.XtraEditors.Repository.RepositoryItemTextEdit();
repositoryItemTextEditReadOnly.Name = "repositoryItemTextEditReadOnly";
repositoryItemTextEditReadOnly.ReadOnly = true;
//...
void gridView1_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e) {
if(e.RowHandle == 0)
e.RepositoryItem = repositoryItemTextEditReadOnly;
}
You can use the ColumnView.ShownEditor event:
void gridView1_ShownEditor(object sender, EventArgs e)
{
ColumnView view = (ColumnView)sender;
view.ActiveEditor.Properties.ReadOnly = view.FocusedRowHandle == 0;
}
Source: How to Conditionally Prevent Editing for Individual Grid Cells
When you need to make a grid cell read-only based on a condition, the
best approach is to use the ShowingEditor event of the
GridView and prevent editing via the e.Cancel parameter passed to the event. Simply set it to True when it is necessary to prevent
editing.
// disable editing
private void gridView1_ShowingEditor(object sender, System.ComponentModel.CancelEventArgs e) {
GridView view = sender as GridView;
e.Cancel = view.FocusedRowHandle == 0;
}
Source - How to display disabled buttons for particular cells within a ButtonEdit column
Another approach is that assign a read only repository editor control as #DmitryG suggested and I have also implement that way some times when there was a column which contains a button.
In your case you should create two TextEdit repository items. One with
the enabled button and another with the disabled button. Then handle
the GridView.CustomRowCellEdit event and pass the necessary
repository item to the e.RepositoryItem parameter according to a
specific condition. Please see the Assigning Editors to Individual
Cells help topic for additional information.
private void gridView1_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
if (e.Column.Caption == "Any2")
{
if (e.RowHandle == 0)
e.RepositoryItem = columnReadOnlyTextEdit;
else
e.RepositoryItem = columnTextEdit;
}
}
References:
How to customize the Look-And-Feel of my grid cells
How to make my grid columns read-only

Datagridview: How to set a cell in editing mode?

I need to programmatically set a cell in editing mode. I know that setting that cell as CurrentCell and then call the method BeginEdit(bool), it should happen, but in my case, it doesn't.
I really want that, with my DGV with several columns, the user can ONLY select and also edit the first two. The other columns are already read-only, but the user can select them, and that is what I don't want.
So I was thinking, tell the user to TAB everytime it has finished writing on the cell, then select the second cell, then tab again and it select and begin edit the next row's first cell...
How can I do this?
Setting the CurrentCell and then calling BeginEdit(true) works well for me.
The following code shows an eventHandler for the KeyDown event that sets a cell to be editable.
My example only implements one of the required key press overrides but in theory the others should work the same. (and I'm always setting the [0][0] cell to be editable but any other cell should work)
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab && dataGridView1.CurrentCell.ColumnIndex == 1)
{
e.Handled = true;
DataGridViewCell cell = dataGridView1.Rows[0].Cells[0];
dataGridView1.CurrentCell = cell;
dataGridView1.BeginEdit(true);
}
}
If you haven't found it previously, the DataGridView FAQ is a great resource, written by the program manager for the DataGridView control, which covers most of what you could want to do with the control.
private void DgvRoomInformation_CellEnter(object sender, DataGridViewCellEventArgs e)
{
if (DgvRoomInformation.CurrentCell.ColumnIndex == 4) //example-'Column index=4'
{
DgvRoomInformation.BeginEdit(true);
}
}
Well, I would check if any of your columns are set as ReadOnly. I have never had to use BeginEdit, but maybe there is some legitimate use. Once you have done dataGridView1.Columns[".."].ReadOnly = False;, the fields that are not ReadOnly should be editable. You can use the DataGridView CellEnter event to determine what cell was entered and then turn on editing on those cells after you have passed editing from the first two columns to the next set of columns and turn off editing on the last two columns.
I know this question is pretty old, but figured I'd share some demo code this question helped me with.
Create a Form with a Button and a DataGridView
Register a Click event for button1
Register a CellClick event for DataGridView1
Set DataGridView1's property EditMode to EditProgrammatically
Paste the following code into Form1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
DataTable m_dataTable;
DataTable table { get { return m_dataTable; } set { m_dataTable = value; } }
private const string m_nameCol = "Name";
private const string m_choiceCol = "Choice";
public Form1()
{
InitializeComponent();
}
class Options
{
public int m_Index { get; set; }
public string m_Text { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
table = new DataTable();
table.Columns.Add(m_nameCol);
table.Rows.Add(new object[] { "Foo" });
table.Rows.Add(new object[] { "Bob" });
table.Rows.Add(new object[] { "Timn" });
table.Rows.Add(new object[] { "Fred" });
dataGridView1.DataSource = table;
if (!dataGridView1.Columns.Contains(m_choiceCol))
{
DataGridViewTextBoxColumn txtCol = new DataGridViewTextBoxColumn();
txtCol.Name = m_choiceCol;
dataGridView1.Columns.Add(txtCol);
}
List<Options> oList = new List<Options>();
oList.Add(new Options() { m_Index = 0, m_Text = "None" });
for (int i = 1; i < 10; i++)
{
oList.Add(new Options() { m_Index = i, m_Text = "Op" + i });
}
for (int i = 0; i < dataGridView1.Rows.Count - 1; i += 2)
{
DataGridViewComboBoxCell c = new DataGridViewComboBoxCell();
//Setup A
c.DataSource = oList;
c.Value = oList[0].m_Text;
c.ValueMember = "m_Text";
c.DisplayMember = "m_Text";
c.ValueType = typeof(string);
////Setup B
//c.DataSource = oList;
//c.Value = 0;
//c.ValueMember = "m_Index";
//c.DisplayMember = "m_Text";
//c.ValueType = typeof(int);
//Result is the same A or B
dataGridView1[m_choiceCol, i] = c;
}
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
{
if (dataGridView1.CurrentCell.ColumnIndex == dataGridView1.Columns.IndexOf(dataGridView1.Columns[m_choiceCol]))
{
DataGridViewCell cell = dataGridView1[m_choiceCol, e.RowIndex];
dataGridView1.CurrentCell = cell;
dataGridView1.BeginEdit(true);
}
}
}
}
}
Note that the column index numbers can change from multiple button presses of button one, so I always refer to the columns by name not index value. I needed to incorporate David Hall's answer into my demo that already had ComboBoxes so his answer worked really well.
The question is old, but the proposed solutions did not help in my situation.
It was necessary to select the cell when loading the form.
This option did not work:
private void FOperations_Load(object sender, EventArgs e)
{
dgvOperations.CurrentCell = dgvOperations[nameof(Operation.DisplayName), 0];
dgvOperations.Select();
}
If you make a cell selection in the "Layout" event, then everything is successful:
private void dgvOperation_Layout(object sender, LayoutEventArgs e)
{
dgvOperations.CurrentCell = dgvOperations[nameof(Operation.DisplayName), 0];
dgvOperations.Select();
}
I know this is an old question, but none of the answers worked for me, because I wanted to reliably (always be able to) set the cell into edit mode when possibly executing other events like Toolbar Button clicks, menu selections, etc. that may affect the default focus after those events return. I ended up needing a timer and invoke. The following code is in a new component derived from DataGridView. This code allows me to simply make a call to myXDataGridView.CurrentRow_SelectCellFocus(myDataPropertyName); anytime I want to arbitrarily set a databound cell to edit mode (assuming the cell is Not in ReadOnly mode).
// If the DGV does not have Focus prior to a toolbar button Click,
// then the toolbar button will have focus after its Click event handler returns.
// To reliably set focus to the DGV, we need to time it to happen After event handler procedure returns.
private string m_SelectCellFocus_DataPropertyName = "";
private System.Timers.Timer timer_CellFocus = null;
public void CurrentRow_SelectCellFocus(string sDataPropertyName)
{
// This procedure is called by a Toolbar Button's Click Event to select and set focus to a Cell in the DGV's Current Row.
m_SelectCellFocus_DataPropertyName = sDataPropertyName;
timer_CellFocus = new System.Timers.Timer(10);
timer_CellFocus.Elapsed += TimerElapsed_CurrentRowSelectCellFocus;
timer_CellFocus.Start();
}
void TimerElapsed_CurrentRowSelectCellFocus(object sender, System.Timers.ElapsedEventArgs e)
{
timer_CellFocus.Stop();
timer_CellFocus.Elapsed -= TimerElapsed_CurrentRowSelectCellFocus;
timer_CellFocus.Dispose();
// We have to Invoke the method to avoid raising a threading error
this.Invoke((MethodInvoker)delegate
{
Select_Cell(m_SelectCellFocus_DataPropertyName);
});
}
private void Select_Cell(string sDataPropertyName)
{
/// When the Edit Mode is Enabled, set the initial cell to the Description
foreach (DataGridViewCell dgvc in this.SelectedCells)
{
// Clear previously selected cells
dgvc.Selected = false;
}
foreach (DataGridViewCell dgvc in this.CurrentRow.Cells)
{
// Select the Cell by its DataPropertyName
if (dgvc.OwningColumn.DataPropertyName == sDataPropertyName)
{
this.CurrentCell = dgvc;
dgvc.Selected = true;
this.Focus();
return;
}
}
}
I finally found an answer to this. In my case, I wanted to select a specific index or item after adding a new row, but this should apply to other situations.
The cell doesnt hold the combobox controls per say. The DGV does, it holds the controls of the current cell. So you have to make the current cell the combo cell, then go in edit mode, then cast the dgv controls as ComboBox, then you will have access to the selectedIndex and selectedItem methods
Dim rowIndex = myDgv.Rows.Add()
myDgv.ClearSelection()
myDgv.CurrentCell = myDgv.Rows(rowIndex).Cells("colName")
myDgv.BeginEdit(True)
Dim myCombo as ComboBox = CType(myDgv.EditingControl, ComboBox)
myCombo.SelectedIndex = 3

Categories

Resources