How To Set ComboBox's SelectedItem Programmatically via Silverlight? - c#

Here's my scenario - I am working with SL3 (and WCF Data Services) and I have a custom form that manages Employees. On the form, I have some simple TextBox(es) and some ComboBox(es) for entering basic information for an Employee. In my architecture, I have some base classes, one to handle the Collections of objects (ObservableCollection and INotifyPropertyChanged implemented) and one that is for the Entity (catches and calls OnPropertyChanged("prop"). In my code behind file (.cs), I have an event handler that handles the _SelectedItemChanged() for the ComboBox(es), for example, EmployeeType, where in the database, values might be like Director, Staff, Reporter, Manager, etc. for the Code column (other columns exist in the EmployeeType table like Description, ModifiedDate, and ID). I have some constructors on my form control, and when I load the form with an empty constructor and thus nothing is loaded (which is the way it should load and correct), everything works perfectly, i.e. I can enter data like FirstName (TextBox), HireData (TextBox), and EmployeeType (ComboBox). The issue I am having is when, I am loading this form, and I know the EmployeeType before-hand, so I don't know how to set the ComboBox's SelectedItem programmatically?
I tried something like this, say I want the form to load the EmployeeType as Manager, so I have in my Load() method:
private SetEmployeeType()
{
var employeeType = new EmployeeType { Code = "Manager" };
this.EmployeeTypeComboBox.SelectedItem = employeeType;
}
But as I'm tracing through my code (F5), I see employeeType as an EmployeeType, but it's properties not fully populated (all blank except for Code as I explicitly called "Manager" above), so when my _SelectedItemChanged() event is called, the .SelectedItem = null, and thus the ComboBox is loaded with nothing picked (the ItemSource is bound to a list and it does come through properly).
FYI, I have other methods where I load my list of EmployeeTypes, e.g. GetEmployeeTypes() and that loads fine. If the ComboBox is blank and then I pick a value, the correct value is submitted to the database, but like I noted, sometimes I want to pre-define the SelectedItem and thus disable the ComboBox to disallow the User from entering invalid data.
I even tried some LINQ like so and it seems not to work:
var type = from e in employeeTypeList // collection loads fine with 10 items
where e.Code = "Manager"
select e;
When I trace through the above query, the 'type' does come back with the correct EntityType object with all of the properties populated (count=1 which is correct), but it doesn't seem to bind to the ComboBox since the ComboBox's SelectedItemChanged() is expecting something like this:
var employeeType = this.EmployeeType.SelectedItem as EmployeeType; // i.e. expecting EmployeeType
but instead, my LINQ query brings back a value of something like:
IEnumerable<EmployeeType> // with some extra stuff...
PS. I am working off from memory since I am currently at home and this is from my code at work, so please excuse me if I am missing something obvious. I have tried different scenarios, and just can't seem to figure it out. Thanks in advance for any assistance!

It sounds like you want to set the selected item to be the manager.
If so, you want something like this:
var type = (from e in employeeTypeList
where e.Code = "Manager"
select e).FirstOrDefault();
EmployeeType.SelectedItem = type;
Your code is creating a list of managers, which even though it has only one item, does not match the data type expected by SelectedItem. The solution to this is to just extract the one item from the list using FirstOrDefault which will give the first item in the list or null if the list is empty.

Try to set the mode to TwoWay instead of Oneway if you have set so.

Related

How can I set ComboBox text to a value not in DataSource (C#)?

I have multiple DropDown-style ComboBoxes on a form in which the user is able to specify which units are associated with a value (think meters, feet, etc.). To do this, I use an application string collection in Settings.Settings with some default unit types which is bound to the DataSource of the ComboBox as follows:
this.cboUnit.DataSource =
(System.Collections.Specialized.StringCollection)Properties.Settings.Default.Units;
The user is able to successfully pick a unit or specify a new one.
Now, when I save this.cboUnit.Text into some XML profile, I am able to handle both cases. Opening the XML profile and performing this.cboUnit.Text = "NonExistentUnit"; will fail and cause the first item in the collection to be selected instead.
How can I modify the ComboBox to support the kind of behavior I'm asking, without adding the item to the ComboBox or modifying the DataSource itself?
There was a solution suggested in Using ComboBox.Text when combobox is tied to DataSource but I couldn't find official documentation to support this behavior. For that reason I prefer to avoid it.
I could not find any valid way to insert items into a bound DataSource. So instead I ended up doing the following:
BindingSource bindingSource = new BindingSource((System.Collections.Specialized.StringCollection)Properties.Settings.Default.Units, "");
if(!bindingSource.Contains(someSavedValue))
{
bindingSource.Insert(0, someSavedValue));
}
this.cboUnit.DataSource = bindingSource;
This creates a new instance of the binding source that can be modified prior to binding it to a data source. I wrapped this code in a method for which I can pass in a string collection and the stored value (savedUnit in this case) that returns a new BindingSource instance. This is especially useful in my case, as I can now simply write:
this.cboLengthUnit.DataSource = CreateBindingSource(unitsCollection, savedLengthUnit);
this.cboWidthUnit.DataSource = CreateBindingSource(unitsCollection, savedWidthUnit);
this.cboHeightUnit.DataSource = CreateBindingSource(unitsCollection, savedHeightUnit);
I wrote the code above from memory, so it may contain a mistake.

Updating a property using the Content Service api in Umbraco 6.x

I've created a custom user control for the back-end of my Umbraco site that allows administrators to quickly update certain fields on nodes without having to navigate through the content tree.
So far my code is working as expected: I can update simple true/false properties without a problem. However now I'm trying to update a property that's of a custom data type and I'm running into difficulties.
The data type itself is just a simple drop down that lists a series of availability statuses ie. Available, Unavailable, Sold and Reserved. The datatype is storing the text values.
Here's the code I have that allows me to update my true/false properties:
public void ChangeInteractiveStatus(string nodeId, bool chkValue)
{
var cs = ApplicationContext.Current.Services.ContentService;
var apartment = cs.GetById(Convert.ToInt32(nodeId));
apartment.SetValue("displayOnInteractive", chkValue);
cs.SaveAndPublish(apartment);
}
This works absolutely fine as the data type of this property is a regular true/false data type.
Here's the code I'm using to change the value of my custom dropdownlist data type:
public void ChangeAvailabilityStatus(string nodeId, string status)
{
var cs = ApplicationContext.Current.Services.ContentService;
var apartment = cs.GetById(Convert.ToInt32(nodeId));
apartment.SetValue("status", status);
cs.SaveAndPublish(apartment);
}
As you can see there's very little difference and yet this code isn't working.
In order to check what was happening when I was updating the properties with the above code, I checked the umbraco.config file only to find that the property in question was displaying as follows:
<status><![CDATA[]]></status>
However when I change the value in the content tree (without using my admin control) the value gets saved properly as:
<status><![CDATA[Sold]]></status>
So for whatever reason, when I try to update the value it's being rejected and I can't work out why.
FYI I tried entering the value as:
"<![CDATA[" + status + "]]>"
Yet that made no difference.
Does anyone know how I can fix this? How can I get the property to update correctly?
Thanks
Okay I've figured out what the problem was. It seems the values were being stored as name-value pairs, so the actual value getting stored in the database was an integer. Once I updated the code to insert the integer id it all worked as expected! Hooray.

Get SharePoint ListItem's After and Before properties in Event Receiver

So I'm trying to accomplish this kind of functionality on my SharePoint 2010 list:
I have a field of type choice in my list, which has 7 values and i want users not to be able to change the value of that field from values 2,3,4,5,6,7 to value 1.
I've written an event receiver for that list, here's my code:
public override void ItemUpdated(SPItemEventProperties properties)
{
base.ItemUpdated(properties);
string beforeStatus = properties.BeforeProperties["Status"].ToString();
string afterStatus = properties.AfterProperties["Status"].ToString();
if (beforeStatus != "1stValue" && afterStatus == "1stValue")
{
properties.Cancel = true;
properties.ErrorMessage = "This isn't allowed.";
}
}
I've tried using both ItemUpdated and ItemUpdating event receivers, when I was debugging I saw that the event receiver get's called as it should be, but beforeStatus and afterStatus is getting null from the item in both cases.
So, how can I get the values of the item's field before and after updating correctly? Thanks in advance!
Note: the field's internal and display names are both Status.
Use ItemUpdating event and then afterproperties contains changed value and ListItem contains original value of a field.
Here you can find info what properties are avaialable in each events.
It is also important how do you edit the list item. If via SharePoint default edit form all columns are present in afterproperties collection, but if you edit an item from custom code (e.g. webpart, event receive) only updated columns are present in that collection.
Edit: For good looking errors you can redirect user to custom error page (which you have to create)
properties.Cancel = true;
properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
properties.RedirectUrl = "/_layouts/MySolution/CustomErrorPage.aspx?Error=" + errorMessage;
I've found a solution to this by myself:
According to this article, I've found out that if I want to get both the old and new values, I have to use ItemUpdating event receiver and use properties.ListItem to get old values and properties.AfterProperties to get the new ones.
Although the error message looks awful to users:
I will try to solve this now :)

ComboBox not updating when object added to bound list

I have an object that represents a client, and that object has a list of the clients branches:
private List<Branch> _branches;
[System.Xml.Serialization.XmlArray("Branches"), System.Xml.Serialization.XmlArrayItem(typeof(Branch))]
public List<Branch> Branches
{
get { return _branches; }
set
{
_branches = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("Branches"));
}
}
}
In one form (WinForms) I have a ComboBox that I've bound to that list:
// creating a binding list for the branches
var bindingList = new BindingList<Branch>(Client.Branches);
// bind list to combo box
cmbBranches.DataSource = bindingList;
cmbBranches.DisplayMember = "Name";
cmbBranches.ValueMember = "Name";
In another function, I create a new Branch object and add it to the existing list: Client.Branches.Add(newBranch). I would expect this to update the ComboBox but it doesn't. Why not, and how do I make it update? (Edit: I'd also like this to update when removing an object from the list. The reason it doesn't work is, I assume, directly related to why the box isn't updating when Add is called.)
In doing research, I found this SO answer, which seems to imply that it will work. I feel like I'm missing something simple ...
difference between ObservableCollection and BindingList
Edit: Some further information about what I've tried and some additional goals.
I cannot use ObservableCollection<T> instead of List<T> as I need to use Exists in the code. Which the former doesn't have.
I need to update the original list when the new object is added, in addition to updating the drop down box.
To summarize my comments below, I attempted adding this:
var bindingList = (BindingList<Branch>) cmbBranches.DataSource;
bindingList.Add(frmAddBranch.NewBranch);
But that results in the object being added to the ComboBox twice. Somehow by calling bindingList.Add it's "resetting" the data source and doubling up. I cannot find any function that "refreshes" the data display once it's bound. Control.ResetBindings() did not work.
Well, it doesn't work that way. The inner List<T> has no change notification mechanism, so adding directly to inner List<T> will not generate any change notification that would eventually reach the combo box. Most convenient way to do what you want is adding the item through the BindingList<T> instead.
I believe you have to add the items directly to the BindingList (but not to the backing Branches list - the BindingList should take care of this for you).

UserControl cannot be displayed in Designer - null object reference

I have a created a UserControl with a combobox in it. This combobox is populated from a xml, when this is not present, it is loaded from resource file.
It works fine in the program, but it can't be displayed in designer - it says: "Object reference not set to an instance of an object."
In the class responsible for loading the list from xml the null reference check is skipped for reasons beyond my understanding...
public SortedDictionary<string, string> Countries
{
get
{
if (object.ReferenceEquals(countries, null))
{
GetCountryList();
}
return countries;
}
}
Populating of the comboBox goes like this:
comboBoxCountry.DataSource = new BindingSource(Program.language.Countries, null);
Program.language is initialized in Program, but it does not help for the Designer.
The question is, how (when, at what event) should I populate the ComboBox (=load list from xml) to be able to display my control in designer.
If possible, you want to check for this.DesignMode and then simply not load the ComboBox at design-time.
Does GetCountryList() set a member variable? If so, move that call to a method. Property get accessors and the ToString() method are assumed pure: the program state before and after must be identical. Violating this assumption can cause all sorts of problems, especially designer/debugger/runtime inconsistency. Various rants have taken place, but the best thing to do is understand the assumption, follow it, and let it work to your advantage as you debug.

Categories

Resources