I need to loop through the properties of a custom object type that I'm getting back from the database and only show the columns that contain data.
This means I cannot simply bind the list of objects to the datagrid.
I don't want to loop through each object and see if the column is empty/null and determine in the UI to display it.
What I'm thinking is in my business layer before I send the object back I would send an IEnumerable back with only those columns that should be visible. Thus I was thinking of using Linq to Object to do this, but I'm not sure that would be very pretty.
Does anyone know of a solution that I could use without a ton of IF statements that I could do to check through a large object (30 or so columns) to determine what should be shown or not.
Foreach (CustomerData customerdata in Customers)
{
if (!customerdata.address.Equals(""))
{
dgvCustomerData.Column["Address"].visible = false;
}
//Continue checking other data columns...
}
I wish to avoid all of this in the UI and all the IFs...
I'm having a brain fart on this one can anyone help me?
Thanks
You could do the following to simplify it a bit
Action<T,string> del = (value,name) => {
if ( value.Equals("") ) {
dgvCustomerData.Column[name].Visible = false;
}
};
foreach ( var data in Customers ) {
del(data.address,"Address");
del(data.name, "Name");
...
}
Take a look at the .NET Reflection Libraries. You can use reflection to get ahold of all of an object's properties, and loop through them to find out if they are null or not. Then you could return a collection of KeyValuePair objects where Key = property name, and Value = true/false. You'd then use the keyvaluepairs to set column visibility...
Related
Consider the following code:
foreach (Type formType in allFormsToLoopThrough)
{
var nonPriorityForm = _context.Query(formType);
foreach (var nonpriority in nonPriorityForm)
{
var name = nonpriority.GetType().Name;
MyWorkAssignmentDTO form = new MyWorkAssignmentDTO
{
FormName = formType.Name
Id = nonpriority.Id
};
}
}
This snippet is looping thought a list of types.
Each type is taken from the list and passed to a Query function that returns an IQueryable - basically a list of records in a given table in a database that matches the type.
Then for each of the record sets that come back, I want to loop through those and from each create a new instance of MyWorkAssignmentDTO. I am only interested in a form name (which I can get from formType) but I cannot get nonpriority.Id
I know for sure that every nonpriority will have an Id once it is resolved in the loop.
What I can't do is implement this to work at run time.
Can anyone help?
I was able to use the dynamic keyword instead of var. While I lose compile time validation, this gets me over the line when I know for sure there will be an Id.
dynamic nonPriorityForm = _context.Query(formType);
I'm trying to automatically create a new workitem, after I choosed the project and one of its workitem-types. For test purposes, I'm iterating over all projects and all of their workitem-types, to create for every workitem-type a new workitem. I know, that there are required fields, which have to have a value, before trying to save that workitem. That's why I'm trying to set "default"-values for that field, but if I log the ArrayList, which I get from the .Validate()-method, I can see, that there are the same fields as before. It seems like my allocation to the fields gets ignored.
In the following example, I would have still the field "GemeldetVon" inside the invalidFields list, at the end.
Does anyone seeing, what I'm doing wrong?
Here is my snippet:
foreach (WorkItemType workItemType in workItemTypes)
{
WorkItem workitem = new WorkItem(workItemType);
workitem.Title = "OTRS-TFS-Connector Test-Workitem";
ArrayList requiredFields = workitem.Validate();
if (requiredFields != null) {
foreach(Field f in requiredFields) {
if (f.Name.Equals("GemeldetVon")) {
workitem.Fields["GemeldetVon"].Value = "some Value";
}
if...
}
}
}
ArrayList invalidFields = workitem.Validate();
IIRC you should call the WorkItem.Open or the WorkItem.PartialOpen method before setting Fields' values.
It's done now. It was because of invalid values, which I tried to assign. My example field needs an user as value, an not just some string. It's working, if I assign valid values. Thanks :)
I am looking for help on an issue with NHibernate which has been bugging me for a while now. Long story short:
I’m looking for a way to, in the first level cache, “reset” a property on an entity each time I do an update or an insert.
What I want to achieve is that the property in question will always be considered to be dirty by NHibernate when using dynamic update or insert.
The backstory for this is that I know that, if the transaction was successful, the column that I want to “reset” will be set to Null in the database by a trigger. On the flip side, the first level cache does not know this, and thus NHibernate will think that the property was not updated when I set it to the same value as I did on the previous update/insert. The catch is that my trigger is dependent on this value being set. The resulting mess is that if I want to use dynamic update or insert I’m only able to update/insert an entity once without “refreshing” it afterwards (which I really don’t want to do).
Tips or help would be much appreciated, because I’ve really hit a wall here
NHibernate provides many places for extension. Among them is the Session IInterceptor. There is documentation with many details:
http://nhibernate.info/doc/nh/en/index.html#objectstate-interceptors
In this case, we can create our custom one, which will be observing our entity (for example Client) and a property which must be updated every time (for example Code). So our implementation could look like this:
public class MyInterceptor : EmptyInterceptor
{
public override int[] FindDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types)
{
var result = new List<int>();
// we do not care about other entities here
if(!(entity is Client))
{
return null;
}
var length = propertyNames.Length;
// iterate all properties
for(var i = 0; i < length; i++)
{
var areEqual = currentState[i].Equals(previousState[i]);
var isResettingProperty = propertyNames[i] == "Code";
if (!areEqual || isResettingProperty)
{
result.Add(i); // the index of "Code" property will be added always
}
}
return result.ToArray();
}
}
NOTE: This is just an example! Apply your own logic for checking the dirty properties.
And we have to wrap Session this way:
var interceptor = new MyInterceptor()
_configuration.SetInterceptor(interceptor);
And this is it. While Client is marked as dynamic-update, the property Code will always be set as dirty
<class name="Client" dynamic-update="true" ...
I'm trying to find, then update, a specific DataRow in a DataTable. I've tried a few things based on my searches, and the code below seems to be the closest I can get. The linq will return one row. With that row, I'd like to update column values (Status, StopTime, Duration). I can't for the life of me find how to do this.. I've tried casting, but I'm new to linq and don't see how to update these values.
private DataTable downloadProcStatusTable;
void UpdateDataDownloadProcedureList(ProcedureStats ProcStats)
{
var currentStatRow = from currentStat in downloadProcStatusTable.AsEnumerable()
where currentStat.Field<String>("ProcedureName") == ProcStats.ProcName
select currentStat;
}
Your query as it stands actually gives you an IEnumerable<DataRow>. You need to do this to get the actual row:
var currentStatRow = (from currentStat in downloadProcStatusTable.AsEnumerable()
where currentStat.Field<String>("ProcedureName") == ProcStats.ProcName
select currentStat).SingleOrDefault();
You should then be able to use the currentStatRow variable to modify the column values.
Outline
Load the existing entity from the database (unless you have one that you can re-attach, in which case you could avoid this additional query)
Update the properties as needed
Submit the changes back to the database using SubmitChanges()
Implementation
I wasn't exactly sure where your variables are and the names, but this should give you a good start...
void UpdateDataDownloadProcedureList(ProcedureStats ProcStats)
{
var currentStatRow = (from currentStat in downloadProcStatusTable.AsEnumerable()
where currentStat.Field<String>("ProcedureName") == ProcStats.ProcName
select currentStat).FirstOrDefault();
currentStatRow.Status = ProcStats.Status;
currentStatRow.StopTime = ProcStats.StopTime;
currentStatRow.Duration = ProcStats.Duration;
downloadProcStatusTable.SubmitChanges();
}
I'm now battling with adding items via C# to Sitecore database.
The code below executes correctly, however the items aren't being created.
Also, I noticed, that the item["FieldName"]=value; syntax doesn't actually populate the Fields collection.
And Fields collection on the item seems read only, so I can't just call .Add on it (such method doesn't exist).
So - what is the correct way of creating a child item and populating its fields?
I am using the Master database for both the Sitecore backend and this code.
The code I use below:
using (new Sitecore.SecurityModel.SecurityDisabler())
{
Database db = Factory.GetDatabase(this.Database);
foreach (var vacancy in Articles.Tables[0].Rows)
{
var rootItem = db.GetItem(this.RootItem);
DataRow dr = (DataRow) vacancy;
var newItem = rootItem.Add(string.Format("{0} {1}", dr["numericID"], dr["job_name"]),
db.GetTemplate(new ID("{GUID}")));
newItem.Editing.BeginEdit();
newItem["Job Title"] = dr["job_name"].ToString();//
newItem.Editing.EndEdit();
}
}
More info:
newItem.Template.Fields returns a collection with 100 fields
newItem.Fields returns a FieldCollection with only 9 elements in it.
When I pass through the code newItem["field"].Value = value; it does not increment the newItem.Fields collection count.
Of course the "field" key is consistent with ones present in newItem.Template.Fields[x].Name.
1) Check some things first f.ex:
assing the template to a variable and check what you get there.
and better don't do it by ID rather by path:
var templateItem = db.GetTemplate("yourTemplatePath");
now check whether that is the template you want?
make sure it's published (it can always cause some inconsistencies)
2) As to the fields not being 'visible', have you tried: item.Fields.ReadAll()
3) What do you mean by "items not being created"? how would you check that?
4) Also - are you sure that this.Database == "master" ?
I would recommend two changes:
(1) The item naming approach:
var newItem = rootItem.Add(ItemUtil.ProposeValidItemName(string.Format("{0} {1}", dr["numericID"], dr["job_name"])), db.GetTemplate(new ID("{GUID}")));
This change will handle invalid characters in the proposed name from your other data source.
(2) The field value setting approach:
newItem.Fields["Job Title"].Value = dr["job_name"].ToString();
This will set the raw value of the field to the provided string.
I would suggest setting the field value as
newItem.Fields["Job Title"].Value = dr["job_name"].ToString();//
Everything else looks ok.