First let me say that I've seen similar questions on StackOverflow, but none that I've seen deal specifically with auto-generated columns.
I have a asp:GridView that I am binding to an IEnumerable<Data>, where Data can vary depending on runtime input. However, each Data class shares a couple base properties:
public class BaseData
{
public int ID { get; set; }
public string Name { get; set; }
}
public class AddressData : BaseData
{
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; };
}
public class ContactData : BaseData
{
public string Phone { get; set; }
public DateTime LastUpdated { get; set; }
// tons more public properties...
}
// More classes with lots of different public properties...
These different classes are populated by a database query, so I want to auto-generate columns when I place the data in the GridView because of the large number of different fields. However, I want to display the columns that are in the shared base class first. If I just assign the IEnumerable<Data> to the GridView datasource, the base classes properties are added last to the GridView's columns. I tried remedying the situation like this:
// Callback after getting data from database
public void SetGridView<Data>(IEnumerable<Data> rows) where Data : BaseData
{
// Make sure these columns show up first
BoundField ID = new BoundField() { HeaderText = "ID", DataField = "ID" };
BoundField Name = new BoundField() { HeaderText = "Name", DataField = "Name" };
myGridView.Columns.Clear();
myGridView.Columns.Add(ID);
myGridView.Columns.Add(Name);
myGridView.AutoGenerateColumns = true;
myGridView.DataSource = rows;
myGridView.DataBind();
}
However, this just duplicates the columns at the beginning and end, so the header looks like this:
ID Name Street1 Street2 City State ZipCode ID Name
So is there a way for me to move the columns that I know will be there (base class) to the beginning of the GridView's columns while still having the convenience of auto-generating all the other columns?
Since you are forced to use auto-generated columns, I'd just create an intermediate DataTable to bind the GridView to. In that DataTable object, you can add your columns in the order you prefer. The GridView should then bind in that same order.
Edit:
Modify BaseData, add the following:
private DataTable dataForDisplay;
// This would be overridden by all child classes, adding their columns in the order you want
public virtual DataTable GetDataForDisplay()
{
dataForDisplay = new DataTable();
dataForDisplay.Columns.Add("ID");
dataForDisplay.Columns.Add("Name");
// If you want to change the order, just don't call the base.GetDataForDisplay()
dataForDisplay.Rows.AddRange(this.ID, this.Name);
return dataForDisplay;
}
Then all of the other child classes will override GetDataForDisplay().
Related
I am having simple DTO class. I would like to dynamically set the column order of this dto properties when the results are stored into excel.
Public class Student
{
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
I know there is a way using DataAnnotation Column Order Attribute on each property inside DTO. But is there a way to handle this using code to set the column order of DTO.
I am using simple web application and added System.ComponentModel.DataAnnotation Reference.
If there is a work around without using DataAnnotation to set the column order using code that will be great
What about using a static array inside your class or in a different class which list all columns in the order you want, and while saving to excel you loop through this array first to get columns in the correct order.
Something like that:
public class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<string> OrderedProperties => new List<string> { "LastName", "FirstName", "Id" };
}
public class DataAccess
{
public void SaveStudentToExcel()
{
var student = new Student(); // instead of new this should be your object filled with real data.
foreach (var propName in student.OrderedProperties)
{
var val = student.GetType().GetProperty(propName).GetValue(student, null);
// new cell in excel => with val and propName then save
}
}
}
I have create grid controle and in designer I add 4 columns(BS, Repere, Profil, Quantity),and I want to add new row in click of button, so I use this code:
gridView2.AddNewRow();
gridView2.SetRowCellValue(GridControl.NewItemRowHandle, gridView2.Columns["BS"], rowGridView1["BS"]);
gridView2.SetRowCellValue(GridControl.NewItemRowHandle, gridView2.Columns["Repere"], rowGridView1["Repère"]);
gridView2.SetRowCellValue(GridControl.NewItemRowHandle, gridView2.Columns["Profil"], rowGridView1["Profil"]);
gridView2.SetRowCellValue(GridControl.NewItemRowHandle, gridView2.Columns["Quantity"], quantity.EditValue);
but when I run the code nothing happend,my grid control not binding to any type of data ,How do I solve this problem? , Thanks in advance.
Declare a class that will hold the data for a single Row
class GridRow
{
public string BS { get; set;}
public string Repere { get; set; }
public string Profil { get; set; }
public int Quantity { get; set; }
}
then bind the grid's DataSource property to a list of rows like this
this.gridRows = new List<GridRow>();
this.grid.DataSource = this.gridRows;
then to add a new row do this
this.gridRows.Add(new GridRow() { BS = "some value", Repare = "Some value", Quantity = 10});
this.gridView1.RefreshData();
i have a dataTable like this :
and a second one like this :
how can i replace MIN_QUANTITY,MAX_QUANTITY,DISCOUNT_VALUE from table two by the values in table 1 based on there GEN_CODE
PS:the GEN_CODE in the second table is not unique and can be duplicated and the duplicate rows should also be added in the first table
i tried to use :
Table1.Merge(Table2, false, MissingSchemaAction.Ignore);
but the duplicates rows are not added how should i fix this ?
Assuming you stored every occurrences of table 1 and 2 into a "record" class that has every column of your datatable as a property.
It can be easily done using LINQ.
Let's say that records from table 1 are stored in List<record> List1 and the other records from table 2 in List<records> List2.
foreach (record reference_record in List1)
{
foreach(record record_to_update in List2.Where(x=>x.GEN_CODE == reference_record.GEN_CODE).Select(x=>x).ToList())
{
record_to_update.MIN_QUANTITY = reference_record.MIN_QUANTITY;
record_to_update.MAX_QUANTITY = reference_record.MAX_QUANTITY;
record_to_update.DISCOUNT_VALUE = reference_record.MAX_QUANTITY;
}
}
You'll need to bind your data table on the following class:
public class record
{
public string GEN_CODE { get; set; }
public string PRODUCT_NAME { get; set; }
public string MIN_QUANTITY { get; set; }
public string MAX_QUANTITY { get; set; }
public string DISCOUNT_VALUE { get; set; }
//... add other properties here
}
I have about 5-6 rows of data that I need to display, when I add data I'd like to be able to sort the data in 4 different sections and none of these will be grouped by any column value its simply getting grouped by a SQL value etc.
How do you do this effectively with the objectlistview?
Its pretty straightforward with the standard listview:
listView1.Items[0].Group = listView1.Groups[0];
I can't seem to figure it out in the objectlistview though.
Thanks.
Adding code:
public class AdminHistory
{
public string Ordernr { get; set; }
public string newImei { get; set; }
public string Imei { get; set; }
public string Fel { get; set; }
public string Modell { get; set; }
public string Garanti { get; set; }
public string Datum { get; set; }
public string User { get; set; }
public string Status { get; set; }
}
private void admin_Load(object sender, EventArgs e)
{
List<AdminHistory> list = new List<AdminHistory>();
list.Add(new AdminHistory() { Ordernr = "12345", newImei = "",
Imei = "test", Fel = "test", Modell = "abc",
Garanti = "ja", Datum = "2014-01-01 18:31", User = "123", Status = "waiting"});
adminHistory.SetObjects(list);
}
My objectlistview has the propper aspectnames.
Basically I don't want to group by any of the fields above, I simply want to be able to create a virtual group and group a lot of data into 4 separate groups, then these groups will be displayed in the listview and the user may view them as he/she wishes.
Example image by creators of objectlistview:
http://www.codeproject.com/KB/list/ObjectListView/fancy-screenshot2.png
The grouping in that image does not group by a column, (I think atleast) but rather a virtual group just like I'm trying to achive.
The grouping in that image does not group by a column, (I think atleast) but rather a virtual group just like I'm trying to achive.
The example actually IS grouped by a columns aspect value. But it additionally uses the "Grouping by Ratings" feature using groupColumn.MakeGroupies.
As far as I know, grouping is always bound to a column. However, you could achieve what you want with a small workaround.
"The crucial part to understand is that all model objects that have the same “key” are placed in the same group. By default, the “key” is the aspect of the model object as calculated by the grouping column."
You can return your own "group key" by installing a GroupKeyGetter delegate, but this property is bound to a column. However, you could just use a "spare" column of your choice , install the GroupKeyGetter for it and return the desired "key" which could be anything.
mySortColumnOfChoice.GroupKeyGetter = delegate(object rowObject) {
var key = /* create your key here */
return key;
};
Then use
objectListView1.BuildGroups(mySortColumnOfChoice, SortOrder.None);
to create the group using your "custom" key.
Im using a List<Patient> object as the data source to a data grid view. I need to use concatenation of two string properties in the Patient class as the value of a single text box column.
I know this can be done by using the OnRowDataBound event in the webforms GridView. How to handle this situation in win forms? I cant see OnRowDataBound event in the win forms Data grid view.
For clarification my Patient class is,
public class Patient
{
public string Initials { get; set; }
public string LastName { get; set; }
}
I need to bind the combination of these two properties to a single column called 'Name' in the grid view. And also there are some other properties in the Patient class which are directly mapped to the data grid view columns using the DataPropertyName of columns. So it is tedious to fill all the columns programmatically.
One easy solution is adding a new property that computes the value to your (view) model and binding to this property.
public class Patient
{
public string Initials { get; set; }
public string LastName { get; set; }
public string InitialsAndLastName
{
get { return this.Initials + " " + this.LastName; }
}
}