Dynamically Set Model Properties in ASP.NET MVC - c#

I have a long list of check boxes that I need to display on a form. I get the list of check boxes from a table in the database and render them on the page. When the page is saved, I am saving the field name and value (as they are stored in the database) of each selected item.
I also have a model class that all of these check box fields map to, but I was thinking, since I have the field name and value, I would be able to set only the properties for which I have a field/value.
I was thinking I could just do something like this, but I know the syntax isn't correct:
private void CreatePPAIndication(ReferralFormViewModel viewModel, Guid personId, Guid encId)
{
var ppaIndication = new PPAIndication();
ppaIndication.enterprise_id = "00001";
ppaIndication.practice_id = "0001";
ppaIndication.person_id = personId;
ppaIndication.enc_id = encId;
// set more properties...
// Here is where I would set a property for each selected check box.
foreach (var indication in viewModel.Indications.Where(o => o.IsSelected))
{
var result = "ppaIndication." + indication.FieldName + "(" + indication.FieldValue + ")";
}
// How can I essentially "execute" the string in the line above?
_context.PPAIndications.Add(ppaIndication);
}
So, basically, I am wondering how I can essentially "execute" the "result" string as real code. Thank you in advance for any advice!

you can use reflection for that
something like
GetType().GetProperty(o.FieldName).GetValue(indication, null);
to get the value
or
GetType().GetProperty(o.FieldName).SetValue(indication, o.Value);
to set the value

Related

How to Delete Item in Sitecore and Update All References

I need to programmatically delete items in Sitecore, but if they are being referenced by other items, then I need to update those items to reference some other item.
In the UI, Sitecore provides a dialog box for doing this, but the item.Delete() and item.Recycle() methods don't appear to have any overrides for something similar. I can use Sitecore.Globals.LinkDatabase.GetItemReferrers(item, true) to get the referring items, but I would still need to get the specific fields from those items and update them according to their type.
To the best of my knowledge, as long as the item's ID gets replaced in the referring item's field, the field's type shouldn't matter. One exception would be the Rich Text field type, where links in the HTML have the following format:
So we should be able to do two simple replacements. One for the item ID and one for the lower-cased, unhyphenated ID.
First, get the referring item links, and create the replacement strings.
var links = Sitecore.Globals.LinkDatabase.GetItemReferrers(item, true);
string oldIdWithoutBraces = item.ID.ToString().Replace("{", "").Replace("}", "");
string newIdWithoutBraces = newItem.ID.ToString().Replace("{", "").Replace("}", "");
string oldIdForHyperlinks = oldIdWithoutBraces.ToLower().Replace("-", "");
string newIdForHyperlinks = newIdWithoutBraces.ToLower().Replace("-", "");
Then, for each referring item link, get its referring field and update the item IDs in it.
using (new Sitecore.SecurityModel.SecurityDisabler())
{
foreach (var link in links)
{
var sourceItem = link.GetSourceItem();
var fieldId = link.SourceFieldID;
var field = sourceItem.Fields[fieldId];
sourceItem.Editing.BeginEdit();
try
{
field.Value = field.Value
.Replace(oldIdWithoutBraces, newIdWithoutBraces)
.Replace(oldIdForHyperlinks, newIdForHyperlinks);
}
catch
{
sourceItem.Editing.CancelEdit();
}
finally
{
sourceItem.Editing.EndEdit();
}
}
}
Afterward, the original item can be deleted.
item.Recycle();
Some Sitecore field types (such as Image fields) have a path attribute, which should be updated as well, but it shouldn't be difficult to work that into the code above.

Display object propery in ComboBox

I have a custom object which holds details about a project resource.
Properties are PersonName, Position and Id
If the resource isn't filled, PersonName is set to 'Unassgined'.
To add an object to a Combobox, I do:
var avail = s.GetUnassignedPrintRoles(SprintId);
foreach (var o in avail)
{
cmbRoles.Items.Add(o);
}
This is fine when displaying a list of resources. My object has an overridden ToString() method:
public override string ToString()
{
if(AssignedPerson != null)
return ResourceType + " - " + AssignedPerson.Firstname + " " + AssignedPerson.Surname;
return "Unassigned";
}
But, I have a screen that shows a list of roles that are not assigned. So, I get a list, where the Person is NULL.
But, I want to display the 'Role' in the ComboxBox.
But, my object's ToString shows 'Unassigned'. How can I make it display the Role property? Is there a way to save the object in the Comboxbox item, but display a different propery in the display, other than what I have set in the ToString override?
With regards to my comment, it might be needed to set the DisplayMember and ValueMember properties of the ComboBox, like so;
cmbRoles.DisplayMember = "Role";
cmbRoles.ValueMember = "Id";
cmbRoles.DataSource = avail;
This way your ComboBox will Display the role, but the underlying data will be the ID, So when you select via the SelectedValue property, you'll get the ID.
Have you tried using the DisplayMember property to distinguish the displayed value and the actual value? If you do that, you should be able to set the Role as the displayed entry on the combobox.
cmbRoles.DisplayMember = "" + Role;
cmbRoles.ValueMember = "Id";
cmbRoles.DataSource = avail;
I'm not sure what Role is in your code but you should be able to get the gist from that.
Add this ,
private void InitializeComponent()
{
cmbRoles.ValueMember = "id";
cmbRoles.DisplayMember = "discription";
}
You can remove ToString() altogether by using read-only property:
public string FullInfo
{
get
{
return ResourceType + " - " + AssignedPerson.Firstname + " " + AssignedPerson.Surname;
}
}
then
comboBox.DisplayMember = "FullInfo";
comboBox.ValueMember = "Id";
comboBox.DataSource = avail;
and you can do any kind of properties like this.

combobox item selected To be fixed

I had a databound combobox in my windows form I populate it by a function deptload() IN FORM LOAD
public void DeptcomboLoad()
{
DataTable dt = depttrans.getDeptName();
Cmb_Department.DataSource = dt;
Cmb_Department.DisplayMember = "DepartmentName"; //CHAR
Cmb_Department.ValueMember = "DepartmentPK"; //INT
}
Now when an employee of a department (say accounts DepartmentName="Accounts " , DepartmentPK=23 ) login I want the ComboBox text to be selected as "acounts "
and when I go to get the selected value of the ComboBox I should get 23
I tried
Cmb_Department.selectedtext="Accounts"
Cmb_Department.Text="Accounts"
but its not giving the selected value
Can anyone give a suggestion
Instead of trying to put a value INTO the combobox, try to GET the SelectedItem like this:
string txt= Cmb_Department.SelectedItem.Text
or just:
string txt= Cmb_Department.SelectedText
To change selected value of the combobox you can use
SelectedItem property or SelectedIndex.
Index must be exact number in your data sourse, and Item must be exact object from datasource
You can get it to select the right item by issuing something like this:
Cmb_Department.SelectedValue = 23;
Where 23 comes from some other variable, maybe on another object, maybe from a local variable, whatever works in your case.
Now, to get the selected value you can use this statement:
var val = Cmb_Department.SelectedValue;
To get the selected text (which would be the text associated with the value):
var text = ((DataRow)Cmb_Department.SelectedItem)["DepartmentName"];
The reason I'm prescribing the aforementioned is because the SelectedText property is volatile, and the Text property doesn't always work based on how the DropDownStyle is set.
However, some would probably argue to get the same as the aforementioned you could issue this statement:
var text = Cmb_Department.Text;

Listbox.DisplayMember won't display value from calculated property

I'm using SubSonic 2.2 for my DAL and extended one of my classes with a calculated property that returns a string containing another property with indenting based on the level of the outline at which the item occurs. The code for the property is below. The problem is that when I try to use this property as the DisplayMember for a ListBox control on a form (the reason I wrote it in the first place) it won't work. The ListBox reverts to displaying the ID property which is set as the ValueMember. To test that the property was working I looped through the collection of objects that I was populating the ListBox with and, using MessageBox.Show(obj.property), confirmed that it was indeed returning the value I'm looking for. Am I missing something or should this work? btw - There may be a better way to do the indenting but that's not what I'm after at the moment, thanks!
Code follows:
public partial class InteriorsCategory : ActiveRecord, IActiveRecord
{
public string ListDisplay
{
get
{
string returnValue = "";
for (int i = 1; i < this.SpecLevel; i++)
{
returnValue += " ";
}
returnValue += this.CategoryName;
return returnValue;
}
}
}
<>
I definitely get data in my collection and the binding I'm doing is exactly the same as yours (binding code posted below). The return value of the ListDisplay property that I'm using is a string concatenation of two values in the object. Think of it as a "full name" property that concatenates the FirstName a space and the LastName properties into a single string which it returns. I am trying to bind the ListDisplay property to the DisplayMember property of the listbox, but all that shows in the listbox is the Id field which I am binding to the ValueMember.
private void FillCategories()
{
lstPackageCategories.DataSource = new InteriorsCategoryCollection().Load();
lstPackageCategories.DisplayMember = "CategoryName";
lstPackageCategories.ValueMember = "Id";
((InteriorsCategoryCollection)(lstPackageCategories.DataSource)).Sort("SpecSection", true);
lstPackageCategories.SelectedItem = lstPackageCategories.Items[0];
currentCategory = (InteriorsCategory)lstPackageCategories.SelectedItem;
RefreshAvailableItems();
}
If your able to see your data in the collection, then it sounds like there is a problem on the binding of your ListBox. Here is an example of how I bind a ListBox using a SubSonic collection of values.
ISOCountryCodeCollection countrys =
new ISOCountryCodeCollection().OrderByAsc(ISOCountryCode.Columns.Country).Load();
Country.DataSource = countrys;
Country.DataValueField = "ThreeChar";
Country.DataTextField = "Country";
Country.DataBind();
In the example above, I'm binding the 3 character country code to the "DataValueField" and the full country name to the "DataTextField".

How to display both Name and ID of a program in Dropdownlist control

My project display's program names from the database into dropdownlist and each program has a ID. I want to display both name and id in the dropdownlist so that they can be differenciated from each other.
eg: 'california lifeline (CLA)'
where 'california lifeline' is the name of the program and the id is 'CLA'. I have created a stored procedure which displays data based on the program ID.
This the code of my dropdownlist control.
private void LoadProgramName()
{
_drp_program = (DropDownList)Page.FindControl("bodyuc$drp_program");
dsprg = rProxy.GlobalFetchFromDB(strCountyName, "DBO.oea_sp_get_onoff_programNames");
_drp_program.DataSource = dsprg;
_drp_program.DataTextField = "PROG_NAME";
_drp_program.DataValueField = "PROGRAM_ID";
_drp_program.DataBind(); ;
ListItem lst_prog = new ListItem();
lst_prog.Value = "";
lst_prog.Text = "--Select One--";
_drp_program.Items.Insert(0, lst_prog);
_drp_program.Items.Insert(1, "ALL");
}
BTW, the dropdown is a part of pagecontrol.
Help is Appriceated.
If your GlobalFetchFromDB() returns instances of an object which you can "extend" as a partial class, then I'd add a "helper" property to the class that formats your displayed string.
One advantage to this is that the format can be dependent on the values of other properties in the instance.
For example:
public partial class ProgramItem
{
public string DisplayName { get { return PROG_NAME.ToUpper(); } }
}
Then use _drp_program.DataTextField = "DisplayName";
An alternative is to construct a class that encapsulates the returned items and adds the DisplayName as a decorator.
Instead of binding _drp_program to dsprg, loop through the results in dsprg and add each item individually.
foreach(dsprgObject in dsprg)
{
_drp_program.Items.add(new ListItem(dsprgObject .ColA + " " + dsprgObject .ColB, dsprgObject.PROGRAM_ID));
}
You can try
_drp_program.DataSource = from item in dsprg
select new
{
PROG_NAME = string.Format("{0}({1})", item.PROG_NAME, item.PROGRAM_ID) ,
PROGRAM_ID = item.PROGRAM_ID
};
instead of
_drp_program.DataSource = dsprg;
Usually the fastest way is to concatenate ID and NAME in an SQL query (but you're using an sp so that's a bit difficult). Also, since you binding your control in code, you can concatenate ID and Name in code and populate your dropdownlist manually (either by calling Items.Insert or by binding your dropdown to a collection which members have a field/property that contains the concatenated value). AFAIK, you can only specify a field/property name for DataTextField and DataValueField, no expressions etc...

Categories

Resources