i have set a CellValueChanging event for devexpress grid view cell in which by changing the value of a cell (which is combobox) the value of other cells changes.
when the one of the items is selected, the cell value changing event fires but noting is shows in the other cells but when another combobox item is selected it works very good.
this also occur for each new row.
how can i handle this?
this is the event:
private void windowBasedMainGridView_CellValueChanging(object sender, CellValueChangedEventArgs e)
{
//if the selected column is not int or dbl, set the descritazation to be automatic
if (e.Column.FieldName == "CriterionParameter")
{
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterDiscretization", "Automatic");
string strSelectedColumnName = commonlyUsedMethodsClass.ColumnNameFromColumnCaption(frmMainForm.projectDataSet.Tables[strinputDatatableName], e.Value.ToString());
Type typeOfSelectedParameter = frmMainForm.projectDataSet.Tables[strinputDatatableName].Columns[strSelectedColumnName].DataType;
if ((typeOfSelectedParameter == typeof(double) || typeOfSelectedParameter == typeof(int)))
{
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterDesceretazationMethod", "Linear");
//set the min and max of property
if (typeOfSelectedParameter == typeof(double))
{
List<double> valuesList = commonlyUsedMethodsClass.DoubleListGenerator(frmMainForm.projectDataSet.Tables[strinputDatatableName], strSelectedColumnName);
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterMinimum", valuesList.Min());
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterMaximum", valuesList.Max());
}
else
{
List<int> valuesList = commonlyUsedMethodsClass.IntegerListGenerator(frmMainForm.projectDataSet.Tables[strinputDatatableName], strSelectedColumnName);
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterMinimum", valuesList.Min());
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterMaximum", valuesList.Max());
}
}
else
{
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterDesceretazationMethod", "");
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterMinimum", null);
windowBasedMainGridView.SetFocusedRowCellValue("CriterionParameterMaximum", null);
}
}
the picture below show that the item is selected first(the other cells does not fill automatically):
the below picture is when first select another item of combo box and then select the depth item(other cells are filled automatically based on cellvaluechanging event):
Try add this method at the end of your handler:
windowBasedMainGridView.BeginDataUpdate();
windowBasedMainGridView.EndDataUpdate();
OR:
windowBasedMainGridView.RefreshData();
Also, you may need call PostEditor method:
windowBasedMainGridView.PostEditor();
Related
In my datagridview, i have a textboxcolumn and an editable combobox column in winforms.But while typing the new value in combobox text and pressing the enter key, i am not getting the typed value as the corresponding cell value.Could anyone please help with this.
private void dgv_customAttributes_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
DataGridViewRow row = dgv_customAttributes.CurrentRow;
if (row.Cells[1].Value.ToString() != null)
{
//Here the selectedVal is giving the old value instead of the new typed text
string SelectedVal = row.Cells[1].Value.ToString();
foreach (CustomAttribute attribute in customAttributes)
{
if (row.Cells[0].Value.ToString() == attribute.AttributeName)
{
attribute.AttributeValue = SelectedVal;
break;
}
}
}
}
You need to find out the combo boxes as they are being shown, and attached an event handler to them for when the selected index changes (since it is not possible to obtain that information from the column or the cell themselves).
This means that, unfortunately, capturing the event CellEndEdit is useless.
In the following example, a text box is filled with the chosen option, but you can do anything else, such as selecting a specific value in your enumerated variable or whatever.
void OnEditingControlShowing(DataGridViewEditingControlShowingEventArgs e)
{
if ( e.Control is ComboBox comboEdited ) {
// Can also be set in the column, globally for all combo boxes
comboEdited.DataSource = ListBoxItems;
comboEdited.AutoCompleteMode = AutoCompleteMode.Append;
comboEdited.AutoCompleteSource = AutoCompleteSource.ListItems;
// Attach event handler
comboEdited.SelectedValueChanged +=
(sender, evt) => this.OnComboSelectedValueChanged( sender );
}
return;
}
void OnComboSelectedValueChanged(object sender)
{
string selectedValue;
ComboBox comboBox = (ComboBox) sender;
int selectedIndex = comboBox.SelectedIndex;
if ( selectedIndex >= 0 ) {
selectedValue = ListBoxItems[ selectedIndex ];
} else {
selectedValue = comboBox.Text;
}
this.Form.EdSelected.Text = selectedValue;
}
Find the complete source code for the table in which a column is a combobox in GitHub.
Hope this helps.
I want a Delete button at the end of each row of DataGridView and by clicking that I want to remove the desired row from the binding list which is data source of my grid.
But I can't seem to do it I have created a button object in product class and instantiated it with the unique id to remove that object from list. but button is not showing in the row.
There are TextBoxes in the form and users can enter text, and when they press Add button, a new object of product is instantiated with the provided fields and then it is added to the BindingList.
Finally this list is bound to the DataGridView and details are shown in the grid. (I have done this part).
and at last by clicking save button the list is saved in the DB.
public class Product{
public string Brand { get; set; }
public int ProductPrice { get; set; }
public int Quantity { get; set; }
public product(string brand,int productPrice, int quantity){
this.Brand = brand;
this.ProductPrice = productPrice;
this.Quantity = quantity;
}
}
public partial class MainForm: Form{
.....
BindingList<Product> lProd = new BindingList<Product>();
private void btnAddProduct_Click(object sender, EventArgs e){
string Brand = txtProBrand.Text;
int Price = Convert.ToInt32(txtPrice.Text);
int Quantity = Convert.ToInt32(txtQuantity.Text);
Product pro = new Product(Brand, Price, Quantity);
lProd.Add(pro);
dataGridView1.DataSource = null;
dataGridView1.DataSource = lProd;
}
.....
}
To show a button on DataGridView rows, you should add a DataGridViewButtonColumn to columns of your grid. Here is some common tasks which you should know when using button column:
Add Button Column to DataGridView
Show Image on Button
Set Text of Button
Handle Click Event of Button
Add Button Column to DataGridView
To show a button on each row of your grid, you can add a DataGridViewButtonColumn to columns of your grid programmatically or using designer:
var deleteButton=new DataGridViewButtonColumn();
deleteButton.Name="dataGridViewDeleteButton";
deleteButton.HeaderText="Delete";
deleteButton.Text="Delete";
deleteButton.UseColumnTextForButtonValue=true;
this.dataGridView1.Columns.Add(deleteButton);
Show Image on Button
If you prefer to draw image on button, you should have an image in a resource and then handle CellPainting event of your grid:
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex == dataGridView1.NewRowIndex || e.RowIndex < 0)
return;
if (e.ColumnIndex == dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
var image = Properties.Resources.DeleteImage; //An image
e.Paint(e.CellBounds, DataGridViewPaintParts.All);
var x = e.CellBounds.Left + (e.CellBounds.Width - image.Width) / 2;
var y = e.CellBounds.Top + (e.CellBounds.Height - image.Height) / 2;
e.Graphics.DrawImage(image, new Point(x, y));
e.Handled = true;
}
}
Set Text of Button
You can use either of these options:
You can set Text property of your DataGridViewButtonColumn and also set its UseColumnTextForButtonValue to true, this way the text will display on each cells of that column.
deleteButton.Text="Delete";
deleteButton.UseColumnTextForButtonValue=true;
Also you can use Value property of cell:
this.dataGridView1.Rows[1].Cells[0].Value = "Some Text";
Also as another option, you can handle CellFormatting event of your grid. This way may be useful when you want to set different texts for buttons.
void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//If this is header row or new row, do nothing
if (e.RowIndex < 0 || e.RowIndex == this.dataGridView1.NewRowIndex)
return;
//If formatting your desired column, set the value
if (e.ColumnIndex=this.dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
e.Value = "Delete";
}
}
Handle Click Event of Button
To hanlde clicks on button, you can handle CellClick or CellContentClick event of your grid. Both events fires by click and by pressing Space key.
void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
//if click is on new row or header row
if( e.RowIndex == dataGridView1.NewRowIndex || e.RowIndex < 0)
return;
//Check if click is on specific column
if( e.ColumnIndex == dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
//Put some logic here, for example to remove row from your binding list.
//yourBindingList.RemoveAt(e.RowIndex);
// Or
// var data = (Product)dataGridView1.Rows[e.RowIndex].DataBoundItem;
// do something
}
}
Get data of the record on Click event
You have e.RowIndex, then you can get the data behind the row:
var data = (Product)dataGridView1.Rows[e.RowIndex].DataBoundItem;
// then you can get data.Id, data.Name, data.Price, ...
You need to cast it to the data type of the recore, for example let's say Product.
If the data binding has been setup to use a DataTable, the the type to cast is DataRowView.
You can also use dataGridView1.Rows[e.RowIndex].Cells[some cell index].Value to get value of a specific cell, however DataBoundItem makes more sense.
Note
As mentioned by Ivan in comments, when you use BindingList you don't need to set datasource of grid to null and back to binding list with every change. The BindingList itself reflects changes to your DataGridView.
i have repository radio group in grid control cell, i wanna set checked in repository radio while value from another cell. this my sample:
while ISJAWAB value is 1, repository radio group will be checked in column PILIH.
i have tried simple code but it doesn't work:
private void gridView2_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
{
if (e.Column.FieldName == "PILIH")
{
var val = Convert.ToString(gridView2.GetRowCellValue(e.RowHandle, "ISJAWAB"));
if (val == "1")
{
e.DisplayText = "1"; //nilai 1 untuk select radio
}
}
}
in the repository collection i have set value to 1, and it automatically set check in repository radio group.
need help ??
RadioGroup is not the best choice for the in-place editor in this case, as it gives you redundant functionality to display several choices within single cell. For your purpose you can use CheckEdit. Also, with CustomDrawCell event you will have to actually manually redraw your radio buttons. There's an easier solution utilizing unbound columns.
So I suggest the following solution:
1.Add CheckEdit repository item, set it's CheckStyle property equal to Radio.
2.Make your PILIH column's Unbound Type = Boolean. Assign above mentioned CheckEdit repository item to it's ColumnEdit. Set OptionsColumn.AllowEdit = false.
3.Add gridView2.CustomUnboundColumnData event handler with body like following:
private void gridView2_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
{
if (e.IsGetData && e.Column.FieldName == "PILIH")
{
var row = (DataRow) e.Row;
var val = Convert.ToString(row["ISJAWAB"]));
if (val == "1")
{
e.Value = true;
}
}
}
you must change the type of reposityRadio to Boolean to true instead of 1 :
2nd the PILIH column data source must be type bool
and use this code :
private void gridView2_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
{
if (e.Column.FieldName == "PILIH")
{
var val = Convert.ToString(gridView2.GetRowCellValue(e.RowHandle, "ISJAWAB"));
if (val == "1")
{
gridView2.SetRowCellValue(e.RowHandle, "PILIH", true);
}
}
}
the result should be like this :
I have a datagrid that I fill with data from a database.
When I click on a row, I call the GotFocus method and try to make a button visible if certain requirements are met.
private void dtgVerkoopsdocumenten_GotFocus(object sender, RoutedEventArgs e)
{
DataItem row = (DataItem)dtgVerkoopsdocumenten.SelectedItems[0];
if (row.soort2 == "Factuur")
{
btnBoeking.IsHitTestVisible = true;
btnBoeking.Opacity = 1;
}
else
{
btnBoeking.IsHitTestVisible = false;
btnBoeking.Opacity = 0.5;
}
}
This gives me an error.
Index was out of range. Must be non-negative and less than the size of the collection.
Now when I call the code but from a button click it does it how it's supposed to work.
private void tester_Click(object sender, RoutedEventArgs e)
{
DataItem row = (DataItem)dtgVerkoopsdocumenten.SelectedItems[0];
test.Content = row.soort2;
if (row.soort2 == "Factuur")
{
btnBoeking.IsHitTestVisible = true;
btnBoeking.Opacity = 1;
}
else
{
btnBoeking.IsHitTestVisible = false;
btnBoeking.Opacity = 0.5;
}
}
Why is this?
Why dont you use DataGrid SelectedIndexChanged event?
Wyy use GotFocus that doesnt tell you if user even made a selection to start with,
DataItem row = (DataItem)dtgVerkoopsdocumenten.SelectedItems[0];
Called from gotfocus will fail as you have nothing selected besides having no error check in place to check if selection,
If you use Selection changed events you know the user has made selection changes there are a number of events for selection
before access selected items by index you need to check selected item count is grater than zero condition.
Because dtgVerkoopsdocumenten.SelectedItems are empty and GotFocus event raise before SelectedItemChanged event so we are not sure the dtgVerkoopsdocumenten.SelectedItems have any item or not.
You can check dtgVerkoopsdocumenten.SelectedItems before do anything.
if (dtgVerkoopsdocumenten.SelectedItems != null &&
dtgVerkoopsdocumenten.SelectedItems.Count > 0)
{
DataItem row = (DataItem)dtgVerkoopsdocumenten.SelectedItems[0];
...
}
I have a flexgrid (flex component grid), how do i hide a cell.
For ex: 2nd row and 5th column - i need to hide/remove based on some condition.
for say
if(C1FlexGrid1.Rows[2][5].ToString().Length <0)
{
//I want this to be invisible.
C1FlexGrid1.Rows[2][5].isVisible=false;
}
There is no propery that supports isVisible the way i have used. Any way i can achieve this ? Thanks.
Finally i figured it out:
Create a ownerdrawcell event for your winforms component grid:
componentGrid.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw;
componentGrid.OwnerDrawCell += componentGrid_OwnerDrawCell;
Method
void componentGrid_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
var value = componentGrid.GetCellCheck(e.Row,e.Col);
//Your custom condition
if (value is bool)
{
//Will hide the cell
e.Style.Display = DisplayEnum.None;
}
else
{
//Will show the cell
e.Style.Display = DisplayEnum.Stack;
}
}