Bind object to winForms control element - c#

I have a class named OrganizerNote with fields: public long id; public DateTime CreationDate; public string Title; public string Note;
Also I have a class public class XMLOrganizer that has 1 field:
public List<OrganizerNote> Notes=new List<OrganizerNote>();
For example, I have several objects:
OrganizerNote n1 = new OrganizerNote();
OrganizerNote n2 = new OrganizerNote();
with some data in fields.
Then I create 1 object
XMLOrganizer xmlOrg = new XMLOrganizer();
xmlOrg.Notes.Add(n1);
xmlOrg.Notes.Add(n2);
So I need to bind each xmlOrg.Notes[0] ... xmlOrg.Notes[i] to Row[i] in datagridView control. And fields values would be in columns.
How could I do so?

make
List<OrganizerNote> Notes=new List<OrganizerNote>();
into
BindingList<OrganizerNote> Notes=new BindingList<OrganizerNote>();
and then create a binding source on the form bind that to the database and then set the binding datasource to the Notes field on the XMLOranizer

Related

Binding the value of an object's property to a data bound ComboBox in .NET WinForms

Currently building a WinForms data collection tool using C# and have been able to implement the binding of the values of my underling object/entity's properties to controls on the my form, e.g. TextBoxes, MaskedTextBoxes and Checkboxes to properties on my domain model class (e.g. Person class). However, I have not been able to do this binding successfully with the ComboBox control.
With my Person class looking basically like this:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Gender { get; set; }
}
I am using the ComboBox's DataSource property to bind to a Dictionary and setting the ValueMember and DisplayMember accordingly. Doing so successfully populates that ComboBox with my reference data (display value and coded value) at run-time.
Dictionary<int, string> genderValues = repository.GetGenderValues()
cboGender.DataSource = new BindingSource(genderValues, null);
cboGender.ValueMember = "Key";
cboGender.DisplayMember = "Value";
However, when I try to bind my Person object's property 'Gender' to this ComboBox, following the pattern that worked with other control types (TextBox, CheckBox, etc.)
cboGender.DataBindings.Add(new Binding("ValueMember", _currentPerson, "Gender"));
The value of Gender on my person object is always NULL even after selecting an item in the Gender ComboBox. Perhaps I am overlooking an additional step needed for binding the ValueMember of a ComboBox to a object property?
ValueMember is a string and it does not change with a different selection in the combobox. You need to use one of the Selected... properties. Since it's an int, use SelectedValue.
Maybe this will help:
cboGender.DataBindings.Add("SelectedIndex", genderValues, "Value", false, DataSourceUpdateMode.OnPropertyChanged);

How to get EditValue from CheckedComboBoxEdit

I have a DevExpress CheckedComboBoxEdit on my form.
In designer i had binded this control with BindingSource.
In BindingSource i have objects
public class MyClass
{
public int Id {set;get;}
public string Name {set;get;}
}
I set DisplayMember as Name and set ValueMember as empty so i expect that i got whole object from EditValue.
Now i want to bind this control with my view model
public class MyViewModel{
***
public List<MyClass> TestList{set;get;}
***
public MyViewModel(){
TestList = new List<MyClass>();
}
}
After i run app with this form. Select values in control.
But after i see that MyViewModel.TestList is empty.
And CheckedComboBoxEdit.EditValue contains list of MyClass.Name what is i setted as DisplayMember.
It is possible to bind CheckedComboBoxEdit to property and make taht EditValue retunr whole object?

c# How to call existing item of form having its name stored in new string?

I have multiple datagrids and i would like to move data from one to another.
The problem is:
I have their names "made" into string variables:
string gridfrom = "datagrid" + cplist1.SelectedItem.ToString();
string gridto = "datagrid" + cplist2.SelectedItem.ToString();
In this case, i know that gridfrom = datagridMAR and gridto = datagridAPR
But gridfrom and gridto changes according to the listboxes selected items.
How do i call these objects (already existing in the form) to change its properties? For example:
gridto.DataSource = gridfrom;
Thanks in advance
Let me tell you an elegant way of dealing with this situation without getting into dynamic type loading, etc
Create a custom type, say
class GridName {
public DataGridView Grid {get; private set;}
public string Name {get; private set;}
public GridName(DatagridView grid, string name) {
Grid = grid;
Name = name;
}
public string override ToString() {
return Name;
}
}
Now, instead of adding a string into the cplist1 and cplist2, simply add GridName object into it. It will display the name correctly and also when you want the grid associated with it, you can access the .Grid property
There are many other ways of doing it. For example, you can use ValueMember and DisplayMember property.
I would definitely resist against trying to convert the grid name into a DatagridView object.

C# datagridview set databound column value to a chosen default one

I have a DataGridView bound to a list of custom objects. A column is bound to a double datatype, and when I try to empty its content (to null), it throws a data error indicating DbNull cannot be converted into Double. What I'd like to accomplish is when a user enters a null value for the databound column, I'd like to set it to a default generic value, say 3.0.
I can handle dataerror and replace the value there, but this seems like a hackish solution. What is the recommended way of handling this?
Edit:
Here's my data class. The double datatype mentioned above is USL.
public class SPCModelDTO
{
public string ProcessName { get; set; }
public string CustomerName { get; set; }
public string ModelName { get; set; }
public double USL { get; set; }
}
Here's my code for databinding
dgvModel.DataSource = new BindingList<SPCModelDTO>(modelList);
Matching property name is declared in designer w/ respect to the dataclass properties.
As a side note, I cannot change USL's datatype to a nullable double.
Create a ViewModel which will be bound to the DataGrdiView.
In the ViewModel you can wrap USL in the nullable type
public class SPCModelDTOViewModel: INotifyPropertyChanged
{
private SPCModelDTO _Model;
public double? USL
{
get { return _Model.USL;}
set
{
if(value.HasValue == false)
_Model.USL = 3.0;
else
_Model.USL = value;
this.RaisePropertyChangedEvent();
}
}
//Other model's properties
}
Line this.RaisePropertyChangedEvent(); will notify View(DataGridView) about changes and empty(null) value will be changed to default one
Of course your ViewModel class must implement INotifyPropertyChanged
How to: Implement the INotifyPropertyChanged Interface
for a databound column you can set DataSourceNullValue in DatagridViewColumn.DefaultCellStyle
dgvModel.DataSource = data;
var col = dgvModel.Columns["USL"];
col.DefaultCellStyle.DataSourceNullValue = 3;

Dynamic N columns bind to DetailsView?

I have a stored procedure that return the data below:
HEIGHT LENGTH WEIGHT WIDTH
0 0 0 0
The columns will be dynamic, can have up to N columns.
What I want to do is bind this result to Details View then let user key in the value.
But I have the error below when I bind to Details View:
DetailsView with id 'detailsViewProcessParameter' did not have any properties or attributes from which to generate fields. Ensure that your data source has content.
Here is the method that I use to return list of object then bind to details view:
public static List<object> GetProcessParameters(int formulaId)
{
using (var db = new SurfaceTreatment.SurfaceTreatmentEntities())
{
var paramFormulaId = new SqlParameter { ParameterName = "formulaId", Value = formulaId };
var query = db.Database.SqlQuery<object>("exec usp_GetProcessParameters #formulaId", paramFormulaId).ToList();
return query.ToList();
}
}
I suspect that I should use "select new { PropertyName = Value, PropertyName = Value}" in my LINQ in order to get rid of the error.
But how do I select new when PropertyName(column name) are dynamic?
How do I use reflection to solve this?
Or is there a better way to do this?
The problem here is that you are returning and thus binding a list of objects i.e. List<object> to DetailsView. I suspect that your object doesn't have any public property which DetailsView needs to Generate Rows and thus throws the error.
When using a list to bind to DetailsView ( or say a GridView ), the object in context, which is represented by some Class, MUST have public properties . For example suppose we bind a List of User List<User> to DetailsView, then here the User class MUST have public properties which will form the Rows for DetailsView ( or Columns in GridView).
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Mail { get; set; }
}
With this basic concept, check to see what does your query variable looks like and try to map this query variable to a Class with public properties.
Since in your case Columns are dynamic in nature, You must be first able to determine the total number of columns with there values, construct a corresponding DataTable at runtime and bind that data table to Detailsview.
If you set AutoGenerateRows to true for the control, all the rows should generate automatically. I do not see any need to perform reflection.
Note that any property which is set for DataKeyNames will not be editable.

Categories