WPF : Nullable ComboBox - wpf

I want to have an empty item in the comboBox to allow the user to "Unselect" and keep the comboBox empty (Null value).
How can I do that?

Make your life easier by using a sentinel value. That is, an instance of your view model class that represents nothing.

If you take a look at my blog entry here, you can see a binding solution that doesn't require you to "modify" your VM or to add dummy items into a collection that doesn't really fit with your data.
Basically, you use a CompositeCollection in your XAML, which gives you the ability (for instance) to have numeric values in your combo-box, and the text "Please select..." to designate the place holder, which you can't do if you are binding entirely to numeric fields in your model and relying on that to add this magic value.

Related

How do I pass an extra variable to a a datatemplate

I have a DataTemplate(well two data templates) that I want to use as views for some
basic form viewmodels(that that contain a value and and boolean indicating whether I want to use the value).
I want to use the datatemplate(s) several times for separate form items. I think the right way to do this is to set it as the ContentControl's ContentTemplate (in that case it will have the same data context right?) but I also want to pass the label string and since the label string is part of the ui and doesn't change it seems wrong to put it in the viewmodel object. How do I give access of the label string to the DataTemplate instance?
Just like its name, a DataTemplate is used to template the Data... For example, if you have a class called MyItem which has a Name and Value and you want this shown in a specific way, you'll set a datatemplate for Item and use it whenever needed.
In your case, you're speaking about having very similar views, with only a minor change between them. This minor change (if I understood your question correctly) is not something that comes from the model or from the viewmodel but something which is entirely view-oriented (a different title for the page, for instance).
If you plan on using a different viewmodel for every view, and each viewmodel has a different purpose - I don't see a problem with adding a Title property to the VM and bind to that too (Remember, MVVM is a set of guidelines, not rules...)
If you still rather have it separated from the viewmodel, then you can use an Attached Property. Create an Attached Property called TemplateTitle, for instance, and have each contentcontrol in each view change it. The label, of course, will bind to that Attached Property.

WPF: How to create a collection that can be bound to

My app has a background thread that periodically retrieves data from an external source, in the form of key/value pairs. I would like to expose this data for binding, presumably by storing them in some kind of static(?) model, as the data will be needed by numerous views throughout my app. There are potentially hundreds of these keys, and may be different for each customer, so I can't simply create an INotifyPropertyChanged model with a property for each value.
The app has multiple views visible at any one time, and each of these will have numerous controls (usually textboxes) that I want to bind to individual items in the above collection. When a value in the collection is updated, any controls bound to only that item should change to reflect the new value. I'm assuming an ObservableCollection wouldn't be suitable here, as a change to a single item will result in all controls updating, regardless of which item they are bound to?
To throw a further complexity into the mix, some values (which are numeric) will need formatting for display, e.g. number of decimal places, or adding a suffix such as "volts". The formatting rules are user-defined so I can't hardcode them into (say) the XAML binding's StringFormat expression. Ideally I should be able to access both the raw value (e.g. for calculations), and the formatted version (for display purposes). I'm sure it must be possible to achieve the latter using some clever WPF feature!
I would appreciate any pointers on how I can solve these requirements.
Edit: it's worth mentioning that I've previously tried implementing the model as some kind of collection. The problem is that it won't be initially populated with all values, and these only get added some time later. When they do eventually get added, a bound control doesn't update - presumably because it wasn't initially able to bind to the missing value.
I would take a different approach, namely a variation of Event Aggregation. I would have a single class that manages the overall collection (probably a singleton class like franssu suggested), but instead of binding directly to the collection in that class you create smaller models that are more specific to the individual views.
When your main model receives a new item, it publishes an event, which is consumed by the smaller models who can inspect the new item and determine whether or not they should add that item to their internal collection (the one the individual views are bound to). If it doesn't "belong" to their view, they can simply ignore the event.
You could use similar event publishing for updates to items and such, although if you're binding to the actual items you probably don't need that.
Just implement the INotifyCollectionChanged Interface and the INotifyPropertyChanged and you ll get a Collection like the ObservableCollection.
But rember if you select a Item from your Collection (as example a ObservableCollection) and you change that item your other controls won t update. So if you have a class Person in your Collection and you change the name of one person the other controls won t get the new name of the person.
Inside the Person object you still have to implement the INotifyPropertyChanged Interface and raise the event when your name changes.
So what I want to tell you is: A Collection with the interface INotifyCollectionChanged will only tell the bound controls: There is a new Item, there has been a item removed or a items index changed BUT not if the item itself changes.
So you ll need a Collection that provides the points above and a Item contained by the collection that raises events if a property of it changes.
ObservableCollection is perfect here. You should find that a standard ItemsControl bound to an ObservableCollection will only update the controls of the items that have changed, not every item in the collection.
This is the reason ObservableCollection exists - the events that it raises specifically identify items that have changed, so that the UI can handle them sensibly.
I've tested this locally with a small WPF app and it works fine. Worth noting, though, that a virtualised items panel would probbaly appear to break this behaviour when it scrolls...
EDIT: rereading your question, you actually say "When a value in the collection is updated..." If your collection contains instances of a class, and you update properties on the class, you don't even need ObservableCollection for this to work - you just need the class to implement INotifyPropertyChanged.

Combox with fill-in option

I want to add to WPF Form a ComboBox which is bound to a datasource (in my viewmodel). But besides from the choices in my viewmodel I would also like to add the option of allowing a fill-in value.
How could I achieve something like that in XAML?
The first thing you need to do is turn on isEditable. I'm assuming that you also want to have the new value added to your datasource. If that is true then you will have to do some code since this is not possible with pure xaml. Here is an example of how to do this.

Silverlight Validation Problem

I have a Silverlight control which has a ListBox showing a series of email addresses. The data source is an ObservableCollection of strings (one per email) in the ViewModel. Simple enough!
I wanted to allow in-place editing of the list, by changing the data template from a TextBlock to a TextBox, with a two-way binding.
The problem is this: How do I validate the user edit is a valid email address?
I don't want to save the bound text to the list unless it's valid. I can't throw an exception as it's bound to a string, so there's no Set method to modify.
The only solution I can think of is to create a dummy class with a single Email property just so I can validate the value. I can't believe that's the best way.
Well you've got bigger problems than just the validation. You can't use TwoWay binding when the source object is a string.
It does make some sense to create an AddressEntry class that has an EmailAddress string property. That way you can make two way binding work and it gives you somewhere to write your validation.

Silverlight RadGridView change TextBox background

I am facing a small problem using silver light . I have a RadGridView, with four columns. My second columns contains text boxes and the third column contains validation errors. If the third column contains validation errors, i want the second column background to turn red. How can i do this. I have tried binding the text box background column to a string with the desired color but that does not work. Really stuck here. Any help with be much appreciated.
Regards,
Mateen
Assuming your binding is otherwise valid, you cannot change colour by binding to a text string of a colour. The background property is of type Brush.
You need to either bind to a Brush instead, or use a brush/colour converter to return a Brush instead of a Color/string etc.
Try these links for converter examples:
http://forums.silverlight.net/p/20392/70263.aspx
http://forums.silverlight.net/p/20392/70263.aspx
You need a StringToObjectConverter found here. This class has the advantage that it has wider uses that eliminate the need to create a plethora of similar converters.
Further rather than having the bound object have a property called "Background" which tell the UI to "be red". I would be better that the Model had a property called "Status" which is an enum of the possible states the object is in.
Going further and looking at your specific requirement it would be better that your model exposed a boolean IsValid property which a converter could be applied to. See this blog on a generic BoolToValueConverter.

Resources