Easycomplete Datagridviewcombobox column winforms - c#

I am trying to create a datagridComboBoxcolumn in winforms with Suggestions Based on Loose Character Search similar to Easycomplete combobox. but I want this as Datagridview combobox.
I have created a grid with Datagridviewcombobox column and used autocomplete but it will search only from first characters. I want loose search. I used
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control is DataGridViewComboBoxEditingControl)
{
((ComboBox)e.Control).DropDownStyle = ComboBoxStyle.DropDown;
((ComboBox)e.Control).AutoCompleteSource = AutoCompleteSource.ListItems;
((ComboBox)e.Control).AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
}
}
Please provide me a solution to create this type of datagridviewcombobox.

For that you have to create a custom DataGridiVew control. This is not a one line code or not a single class code. you have to make several classes for that.
public class MyDgv : DataGridView
{
....
}
And also create some classes like DataGridViewComboBoxColumn, DataGridViewComboBoxCell, DataGridViewEditingComboBoxControl
There is a tutorial how to create custom column in datagridview on msdn

Related

How to create subcolumns in RadGridView?

I have 2 RadGridViews. A GridView with packages and a GridView with detail information.
I use Winforms and the RadGridView of Telerik.
I have source like this
private void CreatePackages()
{
var datasource = from s in Something....;
gvPackages.Columns["colType"].IsVisible = false;
gvPackages.GroupDescriptors.Clear();
if ((int)cbddlPackageType.SelectedValue == -1)
{
GroupDescriptor descriptorType = new GroupDescriptor();
descriptorSoort.GroupNames.Add("colType", ListSortDirection.Ascending);
gvPackages.GroupDescriptors.Add(descriptorType);
}
gvPackages.DataSource = datasource;
}
...
private void gvPackages_SelectionChanged(object sender, EventArgs e)
{
OpenDetails(CurrentId);
}
I want to create a grid with the detail information in the same gridview
How do you do that?
Like this:
Well, it's a bit too late I guess. Anyway, maybe this helps some other devlopers facing the same problem.
I think you're looking for Templates. You could add a template in two ways:
1st (in designer):
Click on the three dots in your RadGridView.Templates property.
And then click on "Add".
2nd (programmatically):
GridViewTemplate template = new GridViewTemplate();
radGridView1.Templates.Add(template);
Now once you have added your template to your RadGridView, you can use it with its index like:
GridViewTemplate myTemplate = radGridView1.Templates[0];
Now you can use it as a "normal" RadGridView and e.g. set its DataSource property.
myTemplate.DataSource = lFooBar;

How do I make a DataGridView immediately commit edits?

I have a master-detail layout with a section of popup menus (the Details) and a section with a DataGridView which holds the rows.
The popup-menu state is updated when the selected row in the DataGridView changes and the state in the DGV's selected row should update when the popup-menu changes.
All of this works except the row in the DataGridView doesn't immediately update when I change the value of the popup-menu. I have to select a different row in order to see my edits.
I'm assuming this is because the edit hasn't been committed until the selection changes.
My question is: How do I make the change to the popup become immediately reflected in the DataGridView?
I have experimented with calling EndEdit() in the SelectionChangeCommitted handler for the popup-menu, but this has no effect. I'm interested in a technique that would allow me to create a DataGridView that would behave as if there were no Undo mechanism to begin with. Ideally the solution would be generic and transplantable to other projects.
It looks like existing answers work well with BindingSource. In my case, where DataTable was directly used as a DataSource, they didn't work for some reason.
// Other answers didn't work in my setup...
private DataGridView dgv;
private Form1()
{
var table = new DataTable();
// ... fill the table ...
dgv.DataSource = table;
}
After some hair-pulling, I got it work without adding BindingSource indirection:
// Add this event handler to the DataGridView
private void dgv_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
dgv.BindingContext[dgv.DataSource].EndCurrentEdit();
}
private Form1()
{
dgv.CellEndEdit += dgv_CellEndEdit;
// ...
}
Here's what was going on. The answer was in the properties of the ComboBox instances. I needed to change their DataSourceUpdateMode from OnValidation to OnPropertyChanged. This makes sense. The DataGridView was very likely showing the current state of the data. It was just that the data hadn't been edited yet because focus had not left the ComboBox, validating the input.
Thanks to everyone for your responses.
this works well for me:
private void CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
var dgw = (DataGridView) sender;
dgw.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
Use this extension method. It works for all columns types, not just ComboBoxes:
public static void ChangeEditModeToOnPropertyChanged(this DataGridView gv)
{
gv.CurrentCellDirtyStateChanged += (sender, args) =>
{
gv.CommitEdit(DataGridViewDataErrorContexts.Commit);
if (gv.CurrentCell == null)
return;
if (gv.CurrentCell.EditType != typeof(DataGridViewTextBoxEditingControl))
return;
gv.BeginEdit(false);
var textBox = (TextBox)gv.EditingControl;
textBox.SelectionStart = textBox.Text.Length;
};
}
This method commits every change just after the change is made.
When we have a text column, after typing a character, its value will commit to the DataSource and the editmode of the cell will end.
Therefore current cell should return to edit mode, and position of the cursor set to end of text in order to enable user to continue typing reminder of the text.
Call the DataGridView.EndEdit method.
following will work
_dataGrid.EndEdit()
s fine once you set the value.

DataGridViewComboBox - How to allow any value?

I'm having some trouble with VisualStudio 2010 C# Winforms.
I have created a DataGridView with an unbound column that is of type DataGridViewComboBoxColumn. The column works fine, except unlike a normal ComboBox, I can't seem to type in just any value. I am forced to pick a value from the list.
Is there a property I need to set or another type I can use that will allow me to enter any value in the cell in addition to providing a list to pick a value from?
Thanks!
I don't think there is a property that will allow this, but I found an answer here that worked with a small modification.
Try adding the following 2 event handlers, here assuming a column named comboBoxColumn:
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
ComboBox c = e.Control as ComboBox;
if (c != null) c.DropDownStyle = ComboBoxStyle.DropDown;
}
private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
{
if (e.ColumnIndex == comboBoxColumn.Index)
{
object eFV = e.FormattedValue;
if (!comboBoxColumn.Items.Contains(eFV))
{
comboBoxColumn.Items.Add(eFV);
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = eFV;
}
}
}
DataGridViewComboBoxColumn is designed rather for select from possible values - not for typing data. If you want to add any data, you should do it programmatically for desired DataGridViewComboBoxCell:
((DataGridViewComboBoxCell)dataGridView1[0,0]).Items.AddRange(new string [] {"A","B","C"});

C# Datagridview - Convert TextColumn to ComboBoxColumn

I have a windows forms application containing a datagridview control. The datagridview is populated by the contents of an xml file. At the moment, all of the columns are displayed as datagridviewtextboxcolumns. I want to select one that is populated by a particular xml tag and display it's content in a datagridviewcomboboxcolumn along with 2 other options.
EXAMPLE:
<SMS>
<Number>+447931663542</Number>
<DateTime>2009-07-12T17:00:02</DateTime>
<Message>YES</Message>
<FollowedUpBy>Unassigned</FollowedUpBy>
<Outcome>Resolved</Outcome>
</SMS>
The OUTCOME tag is the column that I would like to be displayed as a comboboxcolumn in the datagridview. If for example the tag is empty and contains no data, then I want to display nothing, but have the comboboxcolumn populated with 3 possible options to choose from (Unresolved, Resolved, Pending). If however the tag contains data, I want that particular item to be displayed in the comboboxcolumn, and have the other two options available to be selected.
Help in achieving this would be appreciated greatly!
Regards,
EDIT:
Currently I use this code:
colOutcome = new DataGridViewComboBoxColumn();
colOutcome.HeaderText = "Outcome";
colOutcome.Width = 90;
colOutcome.Items.AddRange("Resolved", "Unresolved", "Pending");
this.dataGridView1.Columns.Insert(1, colOutcome);
this.dataGridView1.Columns[1].Name = "OutcomeColumn";
This code above populates the combobox. THE PROBLEM IS: When The xml document populates the datagridview, the outcome column just appears as a textbox column, containing the data inbetween the outcome tags in the xml file. My point is, how can i get the datagridview to realise when it reads the outcome column that it needs to be changed into a combobox column and then display the data that way, along with the other potentially selectable options in the combobox?! Currently the datagridview gets populated with all columns as textboxcolumns containing the data, as well as a seperate combobox column which is not what I want. I need the application to merge the outcome column and its data with the code above.
Any ideas?
Updated Answer
You could pass in the XML document to a function that will loop through each node and determine whether it should be a ComboBox one or not i.e. if the name is "Outcome".
private void CreateColumns(XmlDocument doc)
{
foreach (...) // loop through each node in xml document
{
if (node.Name == "Outcome")
{
var items = new List<string>() { "Resolved", "Unresolved", "Pending" };
this.dataGridView1.Columns.Add(CreateComboBoxColumn(node.Name, items));
}
else
{
this.dataGridView1.Columns.Add(String.Format("col{0}", node.Name), node.Name);
}
}
}
Then your code for creating the Outcome column would be:
private DataGridViewComboBoxColumn CreateComboBoxColumn(string colHeaderText, List<string> items)
{
var colOutcome = new DataGridViewComboBoxColumn();
colOutcome.HeaderText = colHeaderText;
colOutcome.Width = 90;
colOutcome.Items.AddRange(items.ToArray());
colOutcome.Name = String.Format("col{0}", colHeaderText);
return colOutcome;
}
You would then just call CreateColumns on the form load event and pass in your XML. You should only need to create the columns once.
My advice would be to have a similar function that will find all the SMS elements and add a new row populating it with the information in each node.
public void MyForm_Load(object sender, EventArgs e)
{
var doc = new XmlDocument(filename);
CreateColumns(doc);
CreateRows(doc);
}
Hope that helps.
Answer #2 for me, based on the updated question.
The problem you are experiencing is with the AutoGeneratedColumns functionality of the DataGridView. You will need to create your columns manually before databinding. This can be done at design-time or run-time. I prefer design-time because it gives you a bit more direction with the look/feel of the grid but either way works.
You will need to disable the AutoGeneratedColumns property of the grid:
private void Form1_Load(object sender, EventArgs e)
{
// Define your columns at run-time here if that's what you prefer
this.dataGridView1.AutoGeneratedColumns = false;
this.dataGridView1.DataSource = myDataSource;
}
I'm not sitting in front of VS so this might not compile but should give you direction.
You need to either pre-populate the ResolvedColumn with the 3-4 possible values at design-time or assign it to another datasource at runtime. If you chose the design-time approach, simply open the DataGridView "Edit Columns" dialog, find the ResolvedColumn, go to Items, and add your values ("", "Unresolved", "Pending", "Resolved"). The empty value might help the ComboBox to render if there is the possiblity of rendering the grid with SMS records that have no Outcome.
To bind the possible options at runtime do something like this:
private List<string> _outcomeDataSource;
private void Form1_Load(object sender, EventArgs e)
{
_outcomeDataSource = new List<string>;
_outcomeDataSource.Add("");
_outcomeDataSource.Add("Unresolved");
_outcomeDataSource.Add("Pending");
_outcomeDataSource.Add("Resolved");
ResolvedColumn.DataSource = _outcomeDataSource;
ResolvedColumn.PropertyName = "Outcome";
}

How to set DataGridView columns text format to uppercase by adding new property?

I have a custom DataGridView control and want to set the text format for custom columns in the designer (CellStyle builder).
Let's say I want to make the text format to uppercase. After searching about this I've found some solutions with adding new events and then changing the text format but this is not what I want. I want to add a new property to all designed columns and there set or change the text format.
How to do this?
Thank and best regards.
I'm afraid there is no standard property for formatting text how you want.
If you really don't want to use the various DGV events to do your text formatting, you can always create your own DGV components that do what you want and use those in place of the standard DGV components. This article on MSDN should get you started.
EDIT
Here's a blog entry from someone calling himself HanSolo that does what you need.
Here's the code:
public class DataGridViewUpperCaseTextBoxColumn : DataGridViewTextBoxColumn {
public DataGridViewUpperCaseTextBoxColumn() : base() {
CellTemplate = new DataGridViewUpperCaseTextBoxCell();
}
}
public class DataGridViewUpperCaseTextBoxCell : DataGridViewTextBoxCell {
public DataGridViewUpperCaseTextBoxCell() : base() { }
public override Type EditType {
get {
return typeof(DataGridViewUpperCaseTextBoxEditingControl);
}
}
}
public class DataGridViewUpperCaseTextBoxEditingControl : DataGridViewTextBoxEditingControl {
public DataGridViewUpperCaseTextBoxEditingControl() : base() {
this.CharacterCasing = CharacterCasing.Upper;
}
}
Include this code in your project. Once you do so you'll be able to add a new DataGridViewColumn to your DataGridView of type DataGridViewUpperCaseTextBoxColumn. This new DataGridViewColumn uppercases all text entered in the column's TextBox component.
You should also reconsider your decision to not use events. It's pretty easy to do. For example if you have a DGV named dataGridView1 you can use the CellFormatting event like this:
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) {
// Check the value of the e.ColumnIndex property if you want to apply this formatting only so some rcolumns.
if (e.Value != null) {
e.Value = e.Value.ToString().ToUpper();
e.FormattingApplied = true;
}
}
The easy way to edit cells in upper case is add 'EditingControlShowing' event in your DataGridView.
In this event, you can set the 'CharacterCasing' property, in the control that coming with the DataGridViewEditingControlShowingEventArgs parameter.
This Control is based in the Textbox, so you can work like a TextBox!
If the type of column is difrent from DataGridViewTextBoxColumn, the base of control probably has the property 'CharacterCasing'.
I hope, I have help you.
Italo
Use this Simple Method in DataGridView EditingControlShowing "Event"
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
If TypeOf e.Control Is TextBox Then
DirectCast(e.Control, TextBox).CharacterCasing = CharacterCasing.Upper
End If
End Sub

Categories

Resources