I've devexpress XtraGrid populated with data using linq/LinqInstantFeedbackSource. The XtraGrid has a checkEdit repository bind with a column named Status from a table. The data elements in Status column are bits (0 or 1). However, for some unknown reason, the checkEdit could not be selected - i.e. I can't check/uncheck it. What could be the possible reason??
The reason is that the LinqInstantFeedbackSource is a read-only data source.
UPDATE:
As far as I can see you are using the anonymous type as result. Objects of the anonymous type have only read-only properties. It's impossible to modify them. That's why there are no editing in XtraGrid. If you need to obtain a collection of editable objects, don't use anonymous types.
You can use this code, for example:
var tcs=
from tc in dc.TC
join dpt in dc.Departments on tc.DeptID equals dpt.DeptID
where tc.isReturned.Equals(0)
select new EditableObject {
MRN=tc.MRN,
DeptName=dpt.deptName + " - " + dpt.roomNo,
IsReturned= tc.isReturned
};
where EditableObject is:
public class EditableObject{
public string MRN { get; set; }
public string DeptName { get; set; }
public bool IsReturned { get; set; }
}
Related
We are using EF4 database first approach to create all the entities as found in the context class. I'm now trying to add a display name attribute to one of the objects' properties as follows:
[MetadataType(typeof(OpportunityMetaData))]
public partial class Opportunity : EntityObject
{
}
public class OpportunityMetaData
{
[Display(Name = "Worked By")]
public int WorkedById { get; set; }
}
Then on a test page, using reflection, I'm trying to get an output that says "Worked By", as follows:
var attrType = typeof(DisplayNameAttribute);
var property = typeof(Opportunity).GetProperty("WorkedById");
Response.Write(((DisplayNameAttribute)property.GetCustomAttributes(attrType, false).FirstOrDefault()).DisplayName);
But this just gives Object Reference not set to an instance of an object. Alternatively, if I just Response.Write the property, it writes out "WorkedById" and not "Worked By".
Any help would be appreciated.
Its DisplayAttribute, not DisplayNameAttribute. Name is just a property on it.
I've created a Dictionary like
Dictionary<Department,bool> dict= new Dictionary<Department,bool>();
here Department is a class and I have Id,Name and Code for the departments. And in the bool am sending whether the person is HOD or not.
Am adding the records to this Dictionary like
dict.Add(department,chkHOD.checked);
here the records are successfully added to the Dictionary and after this am binding the Dictionary to a GridView like
gridDept.Datasource=dict;
gridDept.Databind();
now the inserted records are displayed fine in the gridview. After this am storing this records in the 'StaffDepartments' table in my database. I have 3 columns in the 'Staffdepartments' table
1.StaffId(PK - has link with the Staff table)
2.DepartmentId(PK - has link with the Department table)
3.IsHOD.
here the records are stored fine in the database.No problem in adding the records into the database.
I have some questions here
*1.How can check whether the DepartmentId is already there in the Dictionary before adding to it.
2.When am editing the staff detail how can I delete the Selected Department from the Dictionary by checking the checkbox in Gridview rows.(here the records are coming from the database, so when I click delete button the records should be deleted in the database as well)*
if its a List instead of Dictionary, I can get the DepartmentId by
int departmentId = (int)gridDept.DataKeys[row.RowIndex].Values["DepartmentId"];
but in Dictionary i dunno how to do the same with Key and Value pairs....can anyone help me here.
How can check whether the DepartmentId is already there in the
Dictionary before adding to it.
You could use this:
if (!dict.Keys.Any(d => d.DepartmentId == department.DepartmentId))
dict.Add(department,chkHOD.checked);
But something is wrong here. If your real key is the DepartmentId and not the Department (object identity) you should make it the key in the dictionary. For example, you could define a helper class:
public class DepartmentBindingHelper
{
public int DepartmentId { get; set; }
public Department Department { get; set; }
public bool Checked { get; set; }
}
An then define a dictionary like this:
var dict = new Dictionary<int, DepartmentBindingHelper>();
And add the objects this way to the dictionary:
if (!dict.ContainsKey(department.DepartmentId))
dict.Add(department.DepartmentId, new DepartmentBindingHelper
{
DepartmentId = department.DepartmentId,
Department = department,
Checked = chkHOD.checked
});
Then you can bind only the value collection to the grid:
gridDept.Datasource = dict.Values;// it's an IEnumerable<DepartmentBindingHelper>
gridDept.Databind();
And your code to retrieve the DepartmentId from a row would work without changes:
int departmentId = (int)gridDept.DataKeys[row.RowIndex].Values["DepartmentId"];
This question, although similar to others, doesn't seem to be a duplicate. If it is, please clarify and I will be happy to merge.
I want to bind to a writable DataGridView using a linq-to-entities query containing a join. The model is as follows:
The denormalized DataGridView should be bound like so:
The following code binds but results in a readonly DataGridView because the linq-to-entities query returns an anonymous type (see this post). I'm at an impasse because I think I need the anonymous type to do the denormalization.
var query = from t in iDictionaryContext.DisplayTexts
from l in iDictionaryContext.Languages
where
t.LanguageID == l.LanguageID
select new
{
Key = t.DisplayKey,
Text = t.DisplayText1,
Language = l.LanguageName
};
I also tried the solution suggested here but it seems to apply to linq-to-sql but not to linq-to-entities. When setting the bindingsource.datasource to the linq-to-entities query, an exception is thrown reading "Only parameterless constructors and initializers are supported in LINQ to Entities."
Thank you for your advice,
Tim
Just define presentation type like that. You don't have to pass objects in constructor:
public class LanguageDisplayTextPresentation
{
public int Key { get; set; }
public string Text { get; set; }
public string Language { get; set; }
}
and then
var query = from t in iDictionaryContext.DisplayTexts
from l in iDictionaryContext.Languages
where
t.LanguageID == l.LanguageID
select new LanguageDisplayTextPresentation
{
Key = t.DisplayKey,
Text = t.DisplayText1,
Language = l.LanguageName
};
Does anybody know if it is possible to choose the order of the fields in Dynamic Data (of course, without customizing the templates of each table) ?
Thanks !
In .NET 4.0, using the 4.0 release of the Dynamic Data dll, you can set data annotations like so:
[Display(Name = " Mission Statement", Order = 30)]
public object MissionStatement { get; set; }
[Display(Name = "Last Mod", Order = 40)]
public object DateModified { get; private set; }
As per this thread - you can use the ColumnOrderAttribute in the dynamic data futures dll. You can grab the futures from codeplex.
You can do this by modifying the order of the public properties in your LINQ to SQL file.
For example, I went into Northwind.designer.cs which was my auto-generated LINQ to SQL file and moved the public property named Products above the public property CategoryName in the public partial class Category. Then I recompiled and the default template displayed the columns in my new order.
Of course, this means your editing auto-generated code and if you regenerate it, your changes are lost, so this technique is not without peril.
You have to create a custom page in DynamicData folder.
Here are the steps:
Create a folder that is the same name as your table name that you want to customize the ordering of columns under "DynamicData\CustomPages" folder
Create a custom page under "DynamicData\CustomPages\[folder with table name]" folder.
I just copy the existing "List.aspx" file from "DynamicData\PageTemplates" into the folder above.
Open the aspx file and modify GridView control to "AutoGenerateColumns='false'"
Inside columns section of GridView, add "DynamicControl" controls with the "DataField" attribute value to the name of your column in the order you want.
Here is a screencast from ScottHa:
http://www.asp.net/learn/3.5-SP1/video-293.aspx
GridView have ColumnsGenerator property, use it by implementing GenerateFields method of IAutoFieldGenerator interface in which you can set fields orders based on your custom rules (attributes, meta info, ...)
protected override void OnInit(EventArgs e)
{
...
this.gvItemsList.ColumnsGenerator = new EntityFieldsGenerator(CurrentDataSource.CurrentTableMetadata);
...
}
public class EntityFieldsGenerator : IAutoFieldGenerator {
...
public ICollection GenerateFields(Control control)
{
// based on entity meta info
var fields = from item in this.entityMetadata.Columns
where this.IncludeColumn(item.Value)
orderby item.Value.Order
select new DynamicField
{
DataField = item.Value.Column.Name,
HeaderText = item.Value.DisplayName,
DataFormatString = item.Value.DataFormatString,
UIHint = GetColumnUIHint(item.Value)
};
return fields.ToList();
} }
To avoid using the Dynamic Data futures dll, you can roll your own ColumnOrder attribute as follows:
[AttributeUsage(AttributeTargets.Property)]
public class ColumnOrderAttribute : Attribute
{
public int Order { get; private set; }
public ColumnOrderAttribute() { Order = int.MaxValue; }
public ColumnOrderAttribute(int order) { Order = order; }
public static ColumnOrderAttribute Default = new ColumnOrderAttribute();
}
and then in your class that implements IAutoFieldGenerator, you have
public static class ExtensionMethods
{
public static int GetOrder (this MetaColumn column)
{
var orderAttribute = column.Attributes.OfType<ColumnOrderAttribute>().DefaultIfEmpty(ColumnOrderAttribute.Default).Single();
return orderAttribute.Order;
}
}
public ICollection GenerateFields(Control control)
{
var fields = new List<DynamicField>();
var columns = _table.Columns.OrderBy(column => column.GetOrder());
foreach (var column in columns)
{
if (!column.Scaffold) { continue; }
fields.Add(new DynamicField {DataField = column.Name});
}
}
and finally your usage would look like
[MetadataType(typeof(CustomerMetadata))]
public partial class Customer {}
public class CustomerMetadata
{
[ColumnOrder(1)]
public object FirstName {get;set;}
[ColumnOrder(2)]
public object LastName {get;set;}
}
I'm answering an old question because it seems to me that the possible solution changed in newer versions of the framework.
It seems that the Display(Order) works now directly as asked (Visual Web Developer 2010 on .NET 4.0) without any particular workaround.
Example:
[Display(Order = 50)]
An important thing it's to check the correct object name to map the foreignkey:
in one project a field OperatoreID translated in the entity class as:
public object Operatore { get; set; }
being Operatore the source table of the foreignkey; for a second reference on the same table it will get something like 1 and so on.
I have problem with gridview deleting.I have table name Doctor with
Id,Name,Address,Phone.Id is auto generated field.After adding data
when i am displaying in gridview then if delete any id from gridview
Again then if i add any new details from the form its starting from
the new number.I mean if i delete the last id no 5 then again if i
add any new doctor its taking id value 6 not from 5.My query is it
should start again from 5.Here is my code.Pls help me.
public class Doctor
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
public static class DoctorDataLayer
{
public static void AddDoctor(Doctor doctor)
{
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; // JohannesH: Changed from .ToString() to .ConnectionString
using(var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand("insert into doctor values(#name,#address,#phone)", connection))
{
command.Parameters.AddWithValue("#name", doctor.Name);
command.Parameters.AddWithValue("#address", doctor.Address);
command.Parameters.AddWithValue("#phone", doctor.Phone);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
}
}
public static class DoctorBusinessLayer
{
public static void CreateDoctor(string name, string address, string phone)
{
DoctorDataLayer.AddDoctor(new Doctor {Name = name, Address = address, Phone = phone});
}
}
This is perfectly normal database behaviour and has nothing to do with your GridView. If you have an issue with gaps in autogenerated (identity) columns, either use your own logic to generate unique ID's or use custom SQL scripts to check for gaps in Identity values and fill those gaps.
Example B in the Transact-SQL reference shows a way to do just this.
So the Id is created by the database (autonumber). When id 5 is used it's used up. This is normal behavior.
As other have noted, if this is an autogenerated ID from the DB then once it is used it will not be regenerated, each ID is unique regardless if the data still exists or not. If IDs were recycled you could get into issues with foreign references that may have pointed to the old item with that ID and now would point to a new different record with the reused ID.
Typically you don't expose the IDs to the user anyway so it is a non issue.
You shouldn't depend on autogenerated ids sequences being ordered or not having gaps. As others have noted, the behavior you are seeing is perfectly normal behavior for an autogenerated id and to make it otherwise you'll need to jump through a lot of hoops. If you need the ids to be ordered by the insertion sequence, you should put in an autogenerated date/time field and then select the data ordered by that field (and index it). That way if you ever decide to switch from a numeric id to a GUID or some other id format in which the sort order is different than the insertion order your data will still be ordered correctly. If you need to have a "place order" for each, generate that automatically (say a rownumber) as you are selecting ordered by date. That way you will still have strict numerical ordering even if records get deleted later.