Telerik Radgrid hierarchical detail grid edit not updating binding list - c#

I need some help here. Here is my situation:
I have a binding list which contains another binding list which I use as data source. below is an example:
Objects:
public class test
{
public string name { get; set; }
public BindingList<childs> childlist { get; set; }
}
public class childs
{
public string childname { get; set; }
}
I populate my radgrid by code. below is a preview:
private void form_Load(object sender, EventArgs e)
{
BindingList<test> testlist = new BindingList<test>();
/** I populate my list with data. I wont show this here. After the list is populated: **//
this.raggrid.MasterTemplate.Columns.Clear();
this.raggrid.MasterTemplate.AutoGenerateColumns = true;
this.raggrid.MasterTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
this.raggrid.MasterTemplate.Columns.Add(new GridViewTextBoxColumn("name", "name"));
GridViewTemplate template = new GridViewTemplate();
this.raggrid.Templates.Add(template);
template.Columns.Add(new GridViewTextBoxColumn("name", "childname"));
template.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
GridViewRelation relation = new GridViewRelation(this.raggrid.MasterTemplate, template);
relation.ChildColumnNames.Add("childlist");
this.raggrid.Relations.Add(relation);
this.raggrid.DataSource = testlist;
}
The populating step works fine. But now, when the user edits the detail grid(named template from the code), I must update the binding list accordingly (named testlist from the code). I cannot seem to trigger an event when I edit the child grid. How do I achieve this?
Note: This is a winform application
PS: When I update the master template the binding list gets updated automatically as expected, but when I update the template I use as detail, it does not update the biding list.
Thanks,
Yash

For anyone having a similar problem, here is the solution:
Solution
Only thing is that I used CellValueChanged event instead of RowsChanged.

Related

Lazy Load Child List Properties in DevExpress Grid (XtraGrid)

I have a simple POCO data structure with what I believe is the correct implementation of loading a list of children in a 'Lazy' manner.
Something like this:
public class Parents
{
public Guid ID { get; set; }
public string Name { get; set; }
//children
private List<Children> childrenList;
public List<Children> ChildrenList
{
get
{
if (childrenList == null) { childrenList = Children.FindByParentID(ID); }
return childrenList;
}
set childrenList = value;
}
}
I need to use a DevExpress XtraGrid control to present the data as it is the control set used by my employer.
I bind the List<Parents> to the grid (e.g. myGrid.DataSource = Parents.FindAll(); ) and everything is fine until I try to expand the first child list using the "+" expansion indicator on the grid.
After I try to expand the first item, the grid (I'm assuming) goes through every parent and tries to load the child list resulting in very slow performance. I can see this while debugging.
I would like the grid to only load the child list for the single item requested. Any ideas about how to achieve this behavior would be very much appreciated.

Wpf DataGrid Set Columns dynamically by list property

I have a small caliburn micro MVVM project with a DataGrid. The columns will consist of x amount of 'setup's and the rows will consist of 'CustomRow'. I would like to use a ObservableCollection where CustomRow has a function property and a collection of setup property. For each setup in this collection a column should exist with the value of setup.
class CustomRow
{
public string Function { get; set; }
public ObservableCollection<Setup> Setups { get; set; }
}
// example class
class Setup
{
public string Name { get; set; }
public object Content { get; set; }
}
So I need to be able to add columns and rows dynamically depending on the itemssource (all the Setups collections will have the same size).
My problem is that I don't know how to translate the Setups property into multiple columns.
I have spend quit some time on what should be a mundane problem in my opinion. But I am missing something.
Any help is much appreciated.
Bind or set the ItemsSource to the ObservableCollection<CustomRow> and then get the Setups property of the first CustomRow in the source collection in the view, e.g.:
private void Window_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var vm = DataContext as YourViewModel;
dataGrid.Columns.Clear();
if (vm.Rows != null && vm.Rows.Count > 0)
{
var setups = vm.Rows[0].Setups;
foreach (var setup in setups)
{
dataGrid.Columns.Add(new DataGridTextColumn { Header = setup.Name, Binding = new Binding("Content ") });
}
}
dataGrid.ItemsSource = vm.Rows;
}
There is no way to bind the Columns property of the DataGrid directly to a source property so you need to create the columns yourself one way or another.
You should do this in the view, in the control or in an attached behaviour that is attached to either of them. A view model should not create any columns.

How to bind container of custom objects at design-time

I want to have a container of objects that will be visualised in WinForms' DataGridView control.
As far as I know, I can bind a container to DataGridView via the DataSource property.
But I wonder, is there any way to do it in Designer? I see a lot of options related to that (like DataSource, DataMember etc) but I don't see any option that will give me a possibility to choose my own container inside the Form class.
I don't want to make this kind of stuff programmatically if it's available in the designer.
DataSource is bindable in designer. You can press the little arrow at the top of the DataGridView, and Choose Data Source. At the bottom> Add Project DataSource...
After adding the class, that will contain Your DataSource, You can set in the properties pane which public property is Your DataSource.
For example:
public class ThereIsDataSourceInThisClass
{
public ThereIsDataSourceInThisClass()
{
MyDataSource = new BindingList<Thing>();
MyDataSource.Add(new Thing { First = "aa", Second = "bb" });
}
public BindingList<Thing> MyDataSource { get; set; }
public class Thing
{
public string First { get; set; }
public string Second { get; set; }
}
}
I selected ThereIsDataSourceInThisClass in the wizard, than I selected MyDataSource in the DataSource property.
The result is>

Binding with object in Windows forms designer

I am trying to bind a list in my namespace to BindingSource through designer. I know how to bind a list in code behind but I would also like to know if it is possible to do the same in designer.
Using the "Data Source Configuration Wizard", I have selected "Object" but it shows only namespace and classes.
I choose a class with List and clicked Finish.
This is the code generated in designer after choosing the class name
this.bindingSource1.DataSource = typeof(Template.Form3);
It looks like windows forms does not have support for binding a list in designer. I am not sure this is the right method or windows forms does not support it. If windows forms have no support for binding to an object, can anyone explain the reason?
Edit:
I tried the suggestion in answer to choose a data member, but it does not bind the binding source with actual data in List. Now designer code looks like
this.bindingSource1.DataMember = "data";
this.bindingSource1.DataSource = typeof(Template.Form3);
The trick is to rebuild your solution, then any public class will be visible in the dropdown list to choose the datasource type from.
Then from the designer, click the binding source (bottom of screen) => Properties => DataMember => Select Property in your class to bind to (A List or Collection)
Edit:
Binding through the designer allows generation of columns at Design time, but it seems that you need to set the BindingSource's Data at runtime.
Since the bind object can't be static memeber but instance member.
private void bindingForm_Load(object sender, EventArgs e)
{
myDataSourceBindingSource.DataSource = (new myDataSource()).MyDataSourceList;
}
Designer:
//
// colADataGridViewTextBoxColumn
//
this.colADataGridViewTextBoxColumn.DataPropertyName = "ColA";
this.colADataGridViewTextBoxColumn.HeaderText = "ColA";
this.colADataGridViewTextBoxColumn.Name = "colADataGridViewTextBoxColumn";
//
// myDataSourceBindingSource
//
this.myDataSourceBindingSource.DataMember = "MyDataSourceList";
this.myDataSourceBindingSource.DataSource = typeof(myNameSpace.myDataSource);
Class:
public class myDataSource
{
public BindingList<myData> MyDataSourceList
{
get
{
var list = new List<myData>()
{
new myData() { ColA = "A" },
new myData() { ColA = "B" }
};
return new BindingList<myData>(list);
}
}
}
public class myData
{
public string ColA { set; get; }
}
I don't know if this makes sense for you, but this is how it works in Windows Forms.

Create a simple DataGridView with List of objects and checkbox column (C#)

I have looked at a lot of places and I'm struggling to do this supposedly simple thing. I have a Windows form on which I've to show a simple DataGridView in this form:
| (CheckBoxColumn) | FilePath | FileState |
Now, there are a couple of problems. The data I need to bind to them is in a List of objects like this:
class FileObject
{
string filePath;
string fileState;
}
//Now here's the list of these objects which I populate somehow.
List<FileObject> listFiles;
Is there any efficient way to bind this directly to the DataGridView
so that different members of Object in the list are bound to
different columns, and for each there's checkbox?
I saw the examples of adding checkbox column to a datagrid, but none of them showed how
to add it to the 'header' row as well, so that it can behave as a 'check all'/'uncheck all' box.
Any help in how to achieve this would be great! I do write simple applications in C# but never had to work with datagrids etc. :(
Thanks!
The DataGridView control has a feature to automatically generate columns that can be set by the AutoGenerateColumns property. This property defaults to true - that is columns are by default auto generated.
However, columns are only automatically generated for public properties of the object you bind to the grid - fields do not show up.
Auto generation also works for check box columns when there is a public boolean property on the bound object.
So the simplest way to achieve your first two requirements is to change your FileObject class to this:
public class FileObject
{
public string FilePath { get; set; }
public string FileState { get; set; }
public bool Selected { get; set; }
}
If you cannot modify that class then next best would be the create a wrapper object that holds a file object:
public class FileObjectWrapper
{
private FileObject fileObject_;
FileObjectWrapper()
{
fileObject_ = new FileObject();
}
FileObjectWrapper(FileObject fo)
{
fileObject_ = fo;
}
public string FilePath
{
get { return fileObject_.filePath; }
set { fileObject_.filePath = value; }
}
public string FileState
{
get { return fileObject_.fileState; }
set { fileObject_.fileState= value; }
}
public bool Selected { get; set; }
}
You can then create your list to bind to (a BindingList is usually best) doing something like:
var fowList = new BindingList<FileObjectWrapper>();
foreach (FileObject fo in // here you have your list of file objects! )
{
fowList.Add(new FileObjectWrapper(fo));
}
dataGridView1.DataSource = fowList;
There are many ways to do the above but that is a general idea.
You can also add an unbound DataGridViewCheckBoxColumn to the grid, though I find it easier to have in the the bound list. Here is how if you do need to:
DataGridViewCheckBoxColumn c = new DataGridViewCheckBoxColumn();
c.Name = "Selected";
dataGridView1.Columns.Add(c);
Finally, for having a "SelectedAll" option in the header you will need to use custom code.
The article on CodeProject that Umesh linked to (CheckBox Header Column for DataGridView) looks quite easy to implement - they create a custom DataGridViewHeaderCell overriding the Paint and OnMouseClick methods.
Please refer the the below example, showing exactly what you are looking for
http://www.codeproject.com/Articles/20165/CheckBox-Header-Column-For-DataGridView

Categories

Resources