How to change RepositoryItem without using CustomRowCellEdit? - c#

I would like to change RepositoryItem in diffrent way than shown in the code bellow. Motivation to do this is described in obsolete field CustomRowCellEditEventArgs.RowHandle.
private void GridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
GridView view = sender as GridView;
if (e.Column.FieldName == CONSTS_FIELD_NAME)
{
var val = (VAL_TYPE) view.GetRowCellValue(e.RowHandle, CONSTS_FIELD_NAME);
if (val == VAL_VALUE)
e.RepositoryItem = new RepositoryItem(); // setting new Repository Item
}
}
So I decided to use this code:
private void GridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
GridView view = sender as GridView;
if (e.Column.FieldName == CONSTS_FIELD_NAME)
{
var result = view.GetSelectedRows();
var val = (VAL_TYPE) view.GetRowCellValue(result.First(), CONSTS_FIELD_NAME);
if (val == VAL_VALUE)
e.RepositoryItem = new RepositoryItem(); // setting new Repository Item
}
}
Is there any other way to change RepositoryItem using some events?

The situation with CustomColumnDataEventArgs you mentioned(providing unbound data for the specific column) have no relation with GridView's editing process. When the CustomRowCellEdit event is fired all the row handles are already calculated. Thus there is no motivation to avoid the first approach.
The only recommendation I can suggest is to use the predefined repository item instead of creating a new one every time:
void GridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e) {
GridView view = sender as GridView;
if(e.Column.FieldName == CONSTS_FIELD_NAME) {
var val = (VAL_TYPE)view.GetRowCellValue(e.RowHandle, CONSTS_VAL);
if(val == VAL_VALUE)
e.RepositoryItem = repositoryItemForVAL_VALUE;
}
}
To use a specific editor for inplace-editing only, you should handle the CustomRowCellEditForEditing event.
Please also carefully read the Remarks section of the GridView.CustomRowCellEdit event documentation which clearly describes how this event works.

Related

How to convert cells of DataGridView to int?

I tried
int A = DataGridView1.Rows[0].Cells[3].value
and
int A = (int)DataGridView1.Rows[0].Cells[3].value
or using Cast or Parse method but it doesn't work.
You shouldn't be doing any of these things.
Your DataGridView should be databound (databind'd) to a DataTable that has a fourth column that is an integer or to a list of objects that has a property that appears in the fourth column of the datagridview, that is an integer:
var x = (int)myDataTableThatTheDGVIsBoundTo.Rows[0][3];
var x = myListOfPeopleWhereAgeAppearsAsDGVFourthColumn[0].Age;
DataGridView is intended for VIEWing a model of data that is kept elsewhere. If you want data out of the model, you get it from the model, not the view. If you want to know something that is eg what the user selected in the view, or is the current row etc you either retrieve the relevant model rows from the SelectedCell's OwningRow.DataBoundItem or use something like a bindingsource that understand sthe concept of "current row"
To really answer this we need a lot more info about how your data got into your grid in the first place. I get the feeling it's not in a model at all :/
try
{
string cellValue = DataGridView1.Rows[0].Cells[3].Value.ToString();
int intCellValue = System.Convert.ToInt32(cellValue);
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
The try-catch block is used in case the user somehow inserted a non-integer value in the datagrid.
Something like that will work too.
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.KeyPress -= new KeyPressEventHandler(Column1_KeyPress);
if (dataGridView1.CurrentCell.ColumnIndex == 0) //Desired Column
{
TextBox tb = e.Control as TextBox;
if (tb != null)
{
tb.KeyPress += new KeyPressEventHandler(Column1_KeyPress);
}
}
}
private void Column1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
Found this code sample on another thread.
dgwProducts.Rows[0].Cells[3].Value
return object.
You can this:
int A = Convert.ToInt32(dgwProducts.Rows[0].Cells[3].Value.ToString());

DevExpress lookupedit repository item add new row in Xtra Grid View in first row

I have a devexpress gridcontrol with 5 columns. The first column is a lookupedit repository with some data, let say with CarTypes.
To load data in grid I am using a BindingSource. In this BindingSource.DataSource I have load a IList<Cars>
and then
added this binding source in dataSource of my gridcontrol
like bellow
BindingSource _carsBindingSource = new BindingSource();
private void BindData(IList<Cars> data)
{
_carsBindingSource.DataSource = data;
carsGridControl.BeginUpdate();
carsGridControl.DataSource = _carsBindingSource;
carsGridControl.RefreshDataSource();
carsGridControl.EndUpdate();
}
I have a button to add new line in my grid "Add new car" and add a new line in _carBindingSource
private void AddNewRow()
{
_newRow = true;
_carsBindingSource.AllowNew = true;
Cars newCar = new Cars();
newCar.CarType = new CarType();
_carsBindingSource.Add(newCar );
//_carsBindingSource.Insert(0,newCar);
}
Now I want to add the new line in the first row of grid.
I use Insert
_carsBindingSource.Insert(0,newCar);
But it didn't work. The lookupedit repository can't load data.
With _carsBindingSource.Add(newCar); it works fine
Can anyone help me? Thank you!
If you haven't already, consider using an intermediate list for your car types:
private List<CarTypes> _CarTypes;
// Elsewhere in the code...
_CarTypes = GetCarTypes();
And then in the form load event, be sure this is bound to the data source:
repositoryLookupItemCarTypes.DataSource = _CarTypes;
With this, the grid should now automatically manage the instantiation and selection of the CarType object for each Cars object. You can omit this line when you add a car to the grid:
newCar.CarType = new CarType();
In the designer, I think it helps to alter the DisplayMember Property of the repository Item.
With this setup, any Car added to your grid should automatically have the CarType as a populated Lookup Edit.
If any of this is unclear, let me know. I did a quick and dirty solution to test this, and I obviously can't post it all, but I can tell you it did work with both Add and Insert.
Actualy I found a solutions.
The problem was in GridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e) event
where I change the AllowEdit value (e.Column.OptionsColumn.AllowEdit = true;).
private void gridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
string cName = e.Column.FieldName;
GridView gv = sender as GridView;
if (cName == "CarType.IdApi")
{
if (isNewRow)
{
Cars cars= (Cars)gv.GetRow(e.RowHandle);
int a = e.RowHandle;
if (cars.ID== 0 && e.RowHandle == 0)
{
e.Column.OptionsColumn.AllowEdit = true;
}
else
{
e.Column.OptionsColumn.AllowEdit = false;
}
}
}
}
When I use Insert(0, new Car) then because of second row whitch has value
the AllowEdit was false;
So I remove else code and it works
private void gridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
string cName = e.Column.FieldName;
GridView gv = sender as GridView;
if (cName == "CarType.IdApi")
{
if (isNewRow)
{
Cars cars= (Cars)gv.GetRow(e.RowHandle);
int a = e.RowHandle;
if (cars.ID== 0 && e.RowHandle == 0)
{
e.Column.OptionsColumn.AllowEdit = true;
}
}
}
}
So finlay I found that bindingSource.Add(object) and bindingSource.Insert(0,object) is same!
I apologize for my english!!

SelectedIndexChanged Not Firing in WinForms for Controls Generated at Runtime

My forehead is bruised from banging my head against my desk on this one.
I have a Form that generates a bunch of custom UserControls (FieldMapper objects) based on parameters passed to it. The FieldMapper UserControl is essentially just a few labels, a BindingSource, and a ComboBox (bound to the BindingSource) organized on a TableLayoutPanel. The ComboBox on this UserControl is set to DropDownList and is bound to the BindingSource, which gets populated with a IList passed as an argument at construction time.
The FieldMapper has an event called MappingChanged, which gets fired whenever the underlying SelectedIndexChanged event is fired and some logic determines the arguments for the MappingChangedEventArgs that are fired with the event. This is used to remove/add items from other comboboxes so nothing can be selected twice in the series of FieldMapping controls
The problem is that ONLY ONE control fires the underlying SelectedIndexChanged event. This control is whatever control I FIRST change it's ComboBox's selected value/index. It doesn't matter which one I select, but only that control will fire subsequent events, although other control's combobox's were changed.
Here is the constructor for the FieldMapper (removed parameters not concerning to the issue)
public FieldMapper(IList<string> fields)
{
InitializeComponent();
fields = fields.OrderBy(s => s).ToList();
string[] copyBuffer = new string[fields.Count + 1];
fields.CopyTo(copyBuffer, 1);
copyBuffer[0] = "NONE";
AvailableMappings = new BindingList<string>(copyBuffer.ToList());
AvailableMappings.RaiseListChangedEvents = true;
bindingSource = new BindingSource();
mapSelector.DataSource = bindingSource;
bindingSource.DataSource = AvailableMappings;
mapSelector.SelectedItem = "NONE";
mapSelector.SelectedIndexChanged += mapSelector_SelectedIndexChanged;
}
The parent Form of these FieldMapper controls generates them as such:
private void BuildMappingTable(IEnumerable<string> fieldNames)
{
int row = 0;
foreach (var field in fbProject.Fields)
{
FieldMapper mapper = new FieldMapper(field.Key, field.Value.FieldName, fieldNames.ToList());
mapper.EnableMappingField = false;
mapper.Anchor = AnchorStyles.Right | AnchorStyles.Left;
mapper.MappingChanged += MappingChanged;
mappingTable.Controls.Add(mapper, 0, row);
row++;
}
if (!built && !original)
SetInitialValues()
built = true;
}
When I check the breakpoints when debugging this issue the event handlers are always populated for both the FieldMapper and the FieldMapper's comobobox's SelectedIndexChanged event, so I'm not sure why they aren't firing.
EDIT: As requested here is the mapSelector_SelectedIndexChanged method
private void mapSelector_SelectedIndexChanged(object sender, EventArgs e)
{
if (currentValue == null || currentValue.Equals("NONE"))
{
currentValue = (string)mapSelector.SelectedItem;
OnMappingChanged(new MappingSelectedEventArgs(MappingSelectedEventArgs.MappingSelectedAction.SET, currentValue));
}
else if (mapSelector.SelectedItem.Equals("NONE"))
{
OnMappingChanged(new MappingSelectedEventArgs(MappingSelectedEventArgs.MappingSelectedAction.REMOVED, currentValue));
currentValue = "NONE";
}
else if (!mapSelector.SelectedItem.Equals(currentValue))
{
OnMappingChanged(new MappingSelectedEventArgs(MappingSelectedEventArgs.MappingSelectedAction.CHANGED, currentValue,
(string)mapSelector.SelectedItem));
currentValue = (string)mapSelector.SelectedItem;
}
}
protected void OnMappingChanged(MappingSelectedEventArgs args)
{
if (MappingChanged != null)
MappingChanged(this, args);
}
Replace:
private void mapSelector_SelectedIndexChanged(object sender, EventArgs e)
by:
private void bindingSource_CurrentChanged(object sender, EventArgs e)

Update DataGrid's ItemsSource on SelectionChanged event of a ComboBox

I subscribed to a SelectionChangedEvent on a ComboBox in a DataGrid with the following code:
public static DataGridTemplateColumn CreateComboboxColumn(string colName, Binding textBinding, SelectionChangedEventHandler selChangedHandler = null)
{
var cboColumn = new DataGridTemplateColumn {Header = colName};
...
if (selChangedHandler != null)
cboFactory.AddHandler(Selector.SelectionChangedEvent, selChangedHandler);
...
return cboColumn;
}
The handler I actually register contains:
private void ComboBoxSelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
Console.WriteLine(#"selectHandler");
var cboBox = sender as ComboBox;
if (cboBox == null)
return;
if (cboBox.IsDropDownOpen) // a selection in combobox was made
{
CommitEdit();
}
else // trigger the combobox to show its list
cboBox.IsDropDownOpen = true;
}
... and is located in my custom DataGrid class.
If I select an item in the ComboBox, e.AddedItems and cboBox.SelectedItem contains the selected value, but nothing is changed on CommitEdit().
What I want is to force a commit to directly update the DataGrid's ItemsSource, when the user selects an item in the drop-down-list. Normally this is raised if the control looses focus...
The link in the solution found in this thread is not available any more and I don't know how to use this code.
I created a tricky, but working, solution for my problem. Here's the modified handler from above:
private void ComboBoxSelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
Console.WriteLine(#"selectHandler");
var cboBox = sender as ComboBox;
if (cboBox == null)
return;
if (cboBox.IsDropDownOpen) // a selection in combobox was made
{
cboBox.Text = cboBox.SelectedValue as string;
cboBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right));
}
else // user wants to open the combobox
cboBox.IsDropDownOpen = true;
}
Because my ComboBoxColumn is a custom DataGridTemplateColumn I force it to show its list, when the user first selects the cell.
To change the bound items value I manually overwrite the displayed text with recently selected item and force the UI to select another item (in this case the control to the right) to make an implicit call to CellEditEnding event, which (in my case) commits the whole row:
private bool _isManualEditCommit = false;
private void _CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
// commit a manual edit
// this if-clause prevents double execution of the EditEnding event
if (!_isManualEditCommit)
{
Console.WriteLine(#"_CellEditEnding() manualeditcommit");
_isManualEditCommit = true;
CommitEdit(DataGridEditingUnit.Row, true);
_isManualEditCommit = false;
checkRow(e.Row);
}
}
Maybe I could help somebody with this "dirty" solution ;-)

Get the ID of the Grid

I have two ASP.NET Grid views, which contain an Image-button, which both call an Edit On-click event. the On-click event looks like:
protected void Edit(object sender, EventArgs e)
{
ImageButton ibtn1 = sender as ImageButton;
using (GridViewRow row = (GridViewRow)((ImageButton)sender).Parent.Parent)
{
txtMessageID.ReadOnly = true;
txtMessageID.Text = row.Cells[2].Text;
txtReference.Text = row.Cells[6].Text;
buttonClicked.Text = ibtn1.ID.ToString();
popup.Show();
}
}
which sole purpose is to fire off a ModalDialogBox, with key items from the grid view being clicked. My problem is that one of the grids doesn't have the Cells[6] (Reference) and therefore falls over. What i need to do is wrap a statement around this cell checking which grid (ID) the button click came from.
I'm not using Row-command, as this wouldn't allow for a single method call from multiple grids. My question is how do I obtain the Grid ID from the Image Button being clicked within this method (see above)?
ended up using the RowCommand of the Gridview, and then used the following to get what i need:
rotected void Edit(object sender, GridViewCommandEventArgs e)
{
ImageButton ibtn1 = sender as ImageButton;
GridView grd = sender as GridView;
string gridName = grd.ClientID;
string buttonId = e.CommandName;
using (GridViewRow row = (GridViewRow)((ImageButton)e.CommandSource).NamingContainer)
{
txtMessageID.ReadOnly = true;
txtMessageID.Text = row.Cells[2].Text;
if (gridName == "grdMessageDups")
{
txtReference.Text = row.Cells[6].Text;
}
buttonClicked.Text = ibtn1.ID.ToString();
popup.Show();
}
}

Categories