Winform DataGridView not show rows - winforms

I bind the DataGridView with datasource (NOT NULL!)
AutoGenerateColumns = false
dgrList.Datasource = mySource;
I have a DataGridView with 4 columns (Design time).
"mySource" contain 3 rows, But the grid didn't make any rows. It's not the case which there are 3 "blank rows" with no-text, it show nothing, like the datasource is null (but not). When I using
foreach(var c in mySource){
dgrList.Rows.add(new object[]....);
}
It's show 3 rows too.
There are no other statement set the datasource, except the one above

You need to set the DataPropertyName for the columns you have created, so that DataGridView knows which properties of the objects to display. E.g. if you have 2 columns (Name and Data):
dgrList.AutoGenerateColumns = false;
dgrList.Columns[0].DataPropertyName = "Name";
dgrList.Columns[1].DataPropertyName = "Data";
dgrList.DataSource = new List<object>()
{
new { Name = "A", Data = 1 },
new { Name = "B", Data = 2 }
};

After you set the DataSource to the datagridview you need to call the DataBind method.
dgrList.Datasource = mySource;
dgrList.DataBind();

Related

Create DataGrid in WPF at runtime

There is a DataGridView which is created at runtime with data fetching from database. There are four types of columns in data grid view:
DataGridViewTextBoxColumn
DataGridViewComboboxColumn
DataGridViewButtonColumn
DataGridViewCheckBoxColumn
Code for creating that datagridview is as below:
_form.DGV_.AutoGenerateColumns = False
_form.DGV_.Columns.Clear()
'Required Variables
Dim pom_DataGridViewTextBoxColumn As DataGridViewTextBoxColumn = Nothing
Dim pom_DataGridViewComboBoxColumn As DataGridViewComboBoxColumn = Nothing
Dim pom_DataGridViewButtonColumn As DataGridViewButtonColumn = Nothing
Dim pom_DataGridViewCheckBoxColumn As DataGridViewCheckBoxColumn = Nothing
'Column-1 (ID: jntDate)
pom_DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn
pom_DataGridViewTextBoxColumn.DataPropertyName = "jntDate"
pom_DataGridViewTextBoxColumn.HeaderText = "Date"
pom_DataGridViewTextBoxColumn.DefaultCellStyle.Format = "d"
_form.DGV_.Columns.Add(pom_DataGridViewTextBoxColumn)
'Column-2 (ID: jntAcc)
pom_DataGridViewComboBoxColumn = New DataGridViewComboBoxColumn
pom_DataGridViewComboBoxColumn.DataPropertyName = "jntAcc"
'Cond: If dataset Acc does not contain any table then add table from database.
If Acc.Tables.Count > 0 Then
pom_DataGridViewComboBoxColumn.DataSource = Acc.Tables.Item(0)
Else
Acc.Tables.Add(Tbl_Select("SELECT *, accNo AS byNo, accName as byName FROM tblAccounts", False, ""))
pom_DataGridViewComboBoxColumn.DataSource = Acc.Tables.Item(0)
End If
'Cond: If _Account_Name_Number is True then set DisplayMember property to 'byName'.
If _Account_Name_Number Then
pom_DataGridViewComboBoxColumn.DisplayMember = "byName"
Else
pom_DataGridViewComboBoxColumn.DisplayMember = "byNo"
End If
pom_DataGridViewComboBoxColumn.ValueMember = "accID"
pom_DataGridViewComboBoxColumn.HeaderText = "Account"
_form.DGV_.Columns.Add(pom_DataGridViewComboBoxColumn)
'Column-3 (ID: xxxx)
pom_DataGridViewButtonColumn = New DataGridViewButtonColumn
pom_DataGridViewButtonColumn.DataPropertyName = "xxxx"
pom_DataGridViewButtonColumn.UseColumnTextForButtonValue = True
pom_DataGridViewButtonColumn.HeaderText = "X"
pom_DataGridViewButtonColumn.Text = "X"
pom_DataGridViewButtonColumn.Width = 32
pom_DataGridViewButtonColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
pom_DataGridViewButtonColumn.DefaultCellStyle.ApplyStyle(pom_DataGridViewButtonColumn.DefaultCellStyle)
_form.DGV_.Columns.Add(pom_DataGridViewButtonColumn)
'Column-4 (ID: jntReview)
pom_DataGridViewCheckBoxColumn = New DataGridViewCheckBoxColumn
pom_DataGridViewCheckBoxColumn.DataPropertyName = "jntReview"
pom_DataGridViewCheckBoxColumn.HeaderText = "Review"
pom_DataGridViewCheckBoxColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
pom_DataGridViewCheckBoxColumn.DefaultCellStyle.ApplyStyle(pom_DataGridViewCheckBoxColumn.DefaultCellStyle)
_form.DGV_.Columns.Add(pom_DataGridViewCheckBoxColumn)
In WPF application, there is a need to populate same DataGrid with these four columns.
How can I create and bind data to four types of columns in DataGrid in WPF ?
Why not skip doing all that stuff in cs code? You'll start pinning yourself in the corner and WILL hit the wall when the datagrid will need more complex templates, data triggers, custom styles, animations, etc... Besides, it will make it easier not only on the next person, but you as well. When you have to add/fix something in the beast you create in .cs code 3-6 months down the road, it might take you quite a while to understand what is going on :)
Instead, do all your work in xaml, Create a UserControl, put this datagrid in it, Pass the DataContext from various instances of the UserControl down to it's DataGrid.

problems setting XtraGrid with in-place editor-s (using GridLookUpEdit)

I need an XtraGrid control that has GridLookupEdit to enter column values.
What I managed to do so far:
1) I have configured XtraGrid control
columns: ID, Name, Number
in-place GridLookUp Editors for Name and Number columns
2) on the form Load event I load data from database and set XtraGrid datasource and both repositoryItem(..) datasource, valuemember and displaymember
a) Data are loaded in XtraGrid, I can activate cell but can not choose values from dropdown (from repositoryItem(..)) or enter values manually (i can activate cell in "*" new row but it has the same problem - can not choose from the dropdown or enter values manually) => why?
b) If I don't set datasource for XtraGrid, then both dropdown's are active and i can select values using GridLookupEdit, but when i exit the cell, the cell gets cleared => i believe this is because in this case no xtraGrid.DataSource is set?
var model = (from TableA a in _dbE.TableA select new {ID, Name, Number}).ToList();
//if i comment this line out, then i can choose values from GridLookUpEdit
gridControl1.DataSource = model;
repositoryItemNosaukums.DataSource = model;
repositoryItemNosaukums.ValueMember = "ID";
repositoryItemNosaukums.DisplayMember = "Name";
repositoryItemPieteikumaNr.DataSource = model;
repositoryItemPieteikumaNr.ValueMember = "ID";
repositoryItemPieteikumaNr.DisplayMember = "Number";
What am I missing?
The problem was, that my data source "model" was a List, but it should have been BindingList with properties AllowNew==True and AllowEdit==True.
After DevExpress support asked if the data source is read only, i found this post which finally opened my eyes:
A Problem in DataGridView : datagridview seems readonly to user (WinForms)
correct version of code
//no projections (select new ...) for IBindingList<T>..
//var model = (from TableA a in _dbE.TableA select new {ID, Name, Number}).ToList();
var model = (from TableA a in _dbE.TableA).ToList();
//convert to BindingList
var bindingModel= new BindingList<TableA>(model);
bindingModel.AllowNew=true;
bindingModel.AllowEdit=true;
//bind BindingList to datagrid
gridControl1.DataSource = bindingModel; //model;
//... no changes to repositoryItem(..) stuff
repositoryItemNosaukums.DataSource = model;
repositoryItemNosaukums.ValueMember = "ID";
repositoryItemNosaukums.DisplayMember = "Name";
repositoryItemPieteikumaNr.DataSource = model;
repositoryItemPieteikumaNr.ValueMember = "ID";
repositoryItemPieteikumaNr.DisplayMember = "Number";

DataGridViewComboBoxCell Value Not Updating When Set Programmatically C# Winforms

I've read all the similiar posts about this darn control (DataGridViewComboBoxCell) and setting it's value programmatically but implementing all the suggestions hasn't worked. I could probably change the UI to get around this problem but I don't like to be beat!
private void PopulateAreaForRoleAssociation()
{
// If businessRoleList is null then no data has been bound to the dgv so return
if (businessRoleList == null)
return;
// Ensure businessArea repository is instantiated
if (businessAreaRepository == null)
businessAreaRepository = new BusinessAreaRespository();
// Get a reference to the combobox column of the dgv
DataGridViewComboBoxColumn comboBoxBusinessAreaColumn = (DataGridViewComboBoxColumn)dgvBusinessRole.Columns["BusinessArea"];
// Set Datasource properties to fill combobox
comboBoxBusinessAreaColumn.DisplayMember = "Name";
comboBoxBusinessAreaColumn.ValueMember = "Id";
comboBoxBusinessAreaColumn.ValueType = typeof(Guid);
// Fill combobox with businessarea objects from list out of repository
comboBoxBusinessAreaColumn.DataSource = businessAreaRepository.GetAll();
// loop through the businessRoles list which the dgv is bound to and get out each dgv row based upon the current id in the loop
businessRoleList.Cast<BusinessRole>().ToList().ForEach(delegate(BusinessRole currentRole)
{
DataGridViewRow currentRowForRole = dgvBusinessRole.Rows.Cast<DataGridViewRow>().ToList().Find(row => ((BusinessRole)row.DataBoundItem).Id == currentRole.Id);
// Get a reference to the comboBox cell in the current row
DataGridViewComboBoxCell comboBoxCell = (DataGridViewComboBoxCell)currentRowForRole.Cells[2];
// Not sure if this is necessary since these properties should be inherited from the combobox column properties
comboBoxCell.DisplayMember = "Name";
comboBoxCell.ValueMember = "Id";
comboBoxCell.ValueType = typeof(Guid);
// Get the business area for the current business role
BusinessArea currentAreaForRole = businessAreaRepository.FetchByRoleId(currentRole.Id);
// if the role has an associated area then set the value of the cell to be the appropriate item in the combobox
// and update the cell value
if (currentAreaForRole != null)
{
foreach (BusinessArea area in comboBoxCell.Items)
{
if (currentAreaForRole.Id == area.Id)
{
comboBoxCell.Value = area.Id;
dgvBusinessRole.UpdateCellValue(2, comboBoxCell.RowIndex);
}
}
}
});
}
The dgv is first bound to a binding list holding BusinessRole objects, then the combobox column is bound to a basic list of BusinessArea objects that come out of a repository class. I then loop through the bindinglist and pull out the row of the dgv that is bound to the current item in the bindinglist loop.
With that row I make a database call to see if the BusinessRole entity is associated with a BusinessArea entity. If it is then I want to select the item in the combobox column that holds the BusinessAreas.
The problem is that when the grid is loaded, all the data is there and the comboboxes are populated with a list of available areas, however any values that are set are not displayed. The code that sets the value is definately getting hit and the value I am setting definately exists in the list.
There are no data errors, nothing. It's just refusing to update the UI with the value I programmatically set.
Any help would be greatly appreciated as always.
Thanks
This code works for my first combo box I have in my row with the following code, but I try it with the next one in the row and it doesn't work. I could use the help with the rest I have 3 more to do. I do set the combo boxes on a second form from this form with the same code as is on the last line of the try block but using the cell information instead of the dataset
try
{
string strQuery = "select fundCode from vwDefaultItems where IncomeType = '" + stIncome + "'";
SqlDataAdapter daDefault = new SqlDataAdapter(strQuery, conn);
DataSet dsDefault = new DataSet();
daDefault.Fill(dsDefault);
strDefFund = dsDefault.Tables[0].Rows[0].ItemArray[0].ToString();
dgvCheckEntry.Rows[curRow].Cells[7].Value = dsDefault.Tables[0].Rows[0].ItemArray[0].ToString();
}
catch (Exception eq)
{
}

Edits to dynamic DataTable not updating in DataGrid

I have a DataTable and when I alter (add,modifiy..ect) it wont reflect on the DataGrid which is bound to the DataTable.
ItemsSource="{Binding TableData,Mode=TwoWay,IsAsync=True}"
Thats the binding ^
Now when I set the RowError
TableData.Rows[x].RowError = ex.Message;
HasError gets set to true... but the DataGrid does not reflect this ( I have a style that marks a row red when there is an error)
Note: My changes are not being reflected on more then setting ErrorMessages, I've also tried adding rows in the ViewModel and those added rows are not relfected either.
About the DataTable:
It has no set columns or anything, it relfects a selected Database table which the user picks.
Binding to a DataTable won't work. You need to first convert your DataTable to an ObservableCollection<>. From here:
public void ConvertDataTable( DataTable dt )
{
DataList = new ObservableCollection<ProjectWorkHours>();
//Scan and arrange data into ObservableCollection
int UserID = 0;
if ( dt.Rows.Count >0 )
{
UserID = int.Parse( dt.Rows[0]["UserID"].ToString() );
//Distill project id list
List<int> ProjectIDList = GetProjectIDList( dt );
for ( int i = 0 ; i < ProjectIDList.Count; i ++ )
{
int ProjectID= ProjectIDList[i];
//Get WorkRecord
int[] MyWorkRecord = GetWorkRecord(dt, ProjectID);
ProjectWorkHours newProjectWorkHours = new ProjectWorkHours(UserID,ProjectID,MyWorkRecord);
DataList.Add( newProjectWorkHours);
}
}
}
The link has a more full example of working with a database and using binding.
What Type is TableData?
If it is a List<> then changing the items in the list will NOT update the binding
If it is an ObservableCollection<> then changing the items in the collection will update the binding

Set DisplayMemberPath and SelectedValue in WPF with Code

I have a DataTable that is coming from a Web Service, which I need to bind to a ComboBox. I have not grokked doing binding in XAML yet so this question is about binding in code instead. So far I have tried
cboManager.DataContext = Slurp.DistrictManagerSelect().DefaultView;
cboManager.DisplayMemberPath = "Name";
cboManager.SelectedValuePath = "NameListId";
cboManager.SetBinding(ComboBox.ItemsSourceProperty, new Binding());
And I have tried
DataTable tbl = new DataTable();
tbl = Slurp.DistrictManagerSelect();
cboManager.ItemsSource = ((IListSource)tbl).GetList();
cboManager.DisplayMemberPath = "[Name]";
cboManager.SelectedValuePath = "[NameListId]";
DataContext = this;
In both cases I get the list of managers to show but when I select from the ComboBox I get [Name] and [NameListId] and not the values I am expecting. What am I doing wrong (other than not using XAML's DataBinding)?
Edit added after answers to my original post came in.
So (based on Rachel's response) try number three looks like this:
using (DataTable tbl = Slurp.DistrictManagerSelect())
{
List<ManagerList> list = new List<ManagerList>();
foreach (var row in tbl.Rows)
{
list.Add(new ManagerList
{
NameListId = (int)row[0],
Name = row[1].ToString()
});
}
}
Assuming I am doing what she meant the correct way I am no getting this error Cannot apply indexing with [] to an expression of type 'object'
Have you tried to just bind to the DataTable directly? Do you have columns Name and NameListId? Leave off the DataContext (you already assigned the ItemsSource).
DataTable tbl = Slurp.DistrictManagerSelect();
cboManager.ItemsSource = tbl;
cboManager.DisplayMemberPath = "Name";
cboManager.SelectedValuePath = "NameListId";
When you cast to the IListSource I suspect it is combining all the columns. If you want to bind to a list then you need to create items that have properties Name and NameListID.
I think that's because your ItemsSource is a DataTable, so each ComboBoxItem contains a DataContext of a DataRow, and the DataRow class doesn't have properties called Name or NameListId
Basically, you're trying to tell the ComboBox to display DataRow.Name, and set the value to DataRow.NameListId, both of which are not valid properties.
I usually prefer to parse data into objects, and bind the ItemsSource a List<MyObject> or ObservableCollection<MyObject>
foreach(DataRow row in tbl.Rows)
list.Add(new MyObject { Name = row[0].ToString(), NameListId = (int)row[1] });
cboManager.ItemsSource = list;

Resources