Im looking forward to writing a combobox with history. Much like address bar, only simpler(no searching, use history only). Since this is quite common, i think maybe there is a library or anything on it. I dont want to write the system from scratch(which ive been doing anyway until i realize its too much work for simple unrequired feature).
So, my question is, how can i have a combobox that can save information that user entered, manage the information that the user entered(delete, rank up/down etc).
Thanks.
i think one solution could be to define an object with hold the entered information and other information like delete command, rank value. then put this object in a observablecollection, use it as the combobox itemsource and whenever a user put something in your comboxbox update your collection in the way you want.
Related
How can I determine when a user has updated the text in a textbox before the Binding has updated the source?
I was expecting to find an "IsDirty" property on either the TextBox or the Binding ...
My problem is that the "Cancel" button Enabled property is bound to the ViewModel's IsDirty property and is disabled until the focus moves out of the textbox.
"IsDirty" needs to be defined as ViewModel.IsDirty || TextBox.IsDirty
WPF can't support the typical IsDirty behaviour that users would expect in a high quality application.
The problem stems from the strange design of the Binder class.
Furthermore WPF architecture is kind of hard-coded to using the default Binder implementation, replacing it is a huge job and requires many "dirty tricks" to work around the endless WPF design flaws.
The easiest way I found to workaround this limitation is to move all value conversion logic to the view model and use UpdateSourceTrigger=PropertyChanged, and implement your own IsDirty and IsInvalid logic and flags.
This approach also plays nicely with Caliburn.Micro
First, why is Cancel disabled? It should be enabled all the time. Any other behavior would be odd. The user should be able to cancel although he hasn't done anything.
Second, I would use Commands so that it can determine whether it can be executed or not based on the state of the viewmodel. Should be easy to implement, if the viewmodel also provide the implementation of the command.
I'd recommend to read some articles and/or tutorials about it. Google for the interface ICommand.
And to answer your question. Assuming you're using binding you could use the INotifyPropertyChanging interface to determine when a value is about to change. You could then store the current value in a backup field or something.
EDIT - Regarding "let him lose data"
Sure it's a valid strategy. Think on a larger input dialog e.g. 5 input controls, which must be validated before persisting the input. I'm assuming that the data is very important according to your arguments. Furthermore, you started to hack your data into the dialog. On input control 3 you decide to press 'ALT + F4'.
First, ask yourself, why did the user press the keys? IMHO he doesn't care about what's happening to his data.
If 'ALT + F4' is just an example for being robust. Forget about it. I think absolute robustness cannot be implemented without being very expensive.
Second, regarding consistency and validity after the restart of the application, you have to throw the data away so that you don't start with an undefined state. Remember, the entity the user began to fill is not valid at this state. Neither the states respectively the values of the properties are.
So IMHO the much better strategy is to restart with a clean and defined state, so that the user is able to continue with whatever you want him to do with your application.
Why is this strategy better? Well, it's much easier to implement. And the much more important argument, the user never gets lost because of an odd state.
I struggle to understand the purpose of the ViewModel sometimes, especially with respect to what it should and shouldn't do.
So... I find myself wanting to expose a display string from my ViewModel. Ok, actually it's a Date string, where I want to display something like "Unknown" if the date isn't set. Really I want a solution to cover the general case, so I don't want a discussion about using null and fallback values. It could equally be a status message like "Awaiting Dispatch" or "Launch Aborted".
So the quesion is, how should the ViewModel expose display strings to the View. The App will need to be localized, so we can't have hard coded strings in the ViewModel.
Is it ok to access the app's resources from the ViewModel, and return the display string?
As an aside, should I be using a resx string resource, or a Xaml resource dictionary? I'm leaning toward the Xaml. Advantages/Disadvantages?
Thanks,
Mark
As mentioned in the other answers, this is clearly the view's responsibility. The view model should expose the data property (a status enum or something similar) for the view to inspect in order to determine the particulars of the display message. From a purist's perspective, generating display properties from the VM or code behind is right out.
I'm surprised to hear no suggestions of datatriggers, though. Use them in your TextBlock to bind to the exposed status enum value and update the text appropriately. This question compares their performance against binding to a converter and suggests that triggers will perform better in this scenario. I haven't done any testing myself, so I'm not sure, but it seems intuitively reasonable to me, provided you aren't listening for an outrageous number of different enum values. I also think it's the more appropriate method in this case, and I'll cite this question asking for a comparison of VC vs. DT use cases, though I don't think it's terribly contentious. To put it another way, if one holds that a VM is a value converter on steroids (a statement which I'm very leery of and will not agree or disagree with at the moment), then this argument holds: a VM shouldn't be exposing display properties; a VM's purpose and abilities are a super-set of those of a VC; therefore, a VC should not be exposing display properties.
I'm doing my best to give the purist's answer (or what I think it is, at least), but there are certainly easier ways to code it than writing a lot of datatriggers, especially if you have many different values to address.
Regarding your resource question, have a look at this MSDN article on resource files, which is, in certain ways, easier to work with than a resx file. Which approach you should use depends on your use cases.
What you are doing is taking data that is inside the system and converting it to a format that makes it more useful and clear to the user. This is the responsibility of the view. It would be the responsibility of the view to format a valid date into the correct culture and it has the same responsibility for any text that you wish to display.
In the same respect the status examples you give would probably be stored as an enum in the viewmodel (since that would make it easier to apply business logic to them, which is the role of the viewmodel) and it would be the responsibility of the view to display the values in a way that works for the user in all respects. This would include size, colour, font, position and culture.
That being said though I have been known to put display logic in my viewmodel (concatenating firstname and surname for example) simply because it is easier. I've even been known to use code-behind (shock, horror!) where it suits my purpose. There is a sliding scale between purity and pragmatism, and it is up to you where you sit on that line.
To display the string Unknown when the date is not set is a display issue and therefore has to be solved in the view. Even "Awaiting dispatch" is a presentation of a value.
So the answer is: The view model should never expose display strings. The view model has to expose a value that leads the view/a converter/whatever object from the presentation layer to choose a display string.
Even if this answer is not the answer you want to read, it is the answer an MVVM purist has to give. And as you asked for MMVM purists, here it is.
For the date, I would have the ViewModel export a nullable DateTimeOffset, where the null value means "not set". The in the View (via a converter or similar), the null value is displayed as whatever you need.
As to the aside: I would use resx. The reason is that there is a defined fallback mechanism when strings aren't available in the language.
An approach I have taken was creating Culture specific Resources and adding instances (singletons?) of these to the ViewModel.
Then the View can simply Bind to the ViewModel.Resource.DisplayString
See this article for Windows Phone 7 which easily translates to WPF.
If you dislike this because you do not want to tie the culture specific resource to the ViewModel and want the View to solve it you could use/write a ValueConverter that turns a value from a VM property into a display string.
I am creating a user control that I would like to be able to generate the form entry fields based on what custom data object the form is bound to. Basically, I have a drop-down box that allows the user to pick what type of data object they are working with (user, address, etc.) That choice will bind the user control to the related data object. No big deal there. I am stuck, however, on how to generate the form fields based on the properties of the object. I feel like I have seen examples of this in WPF but am not able to find them now. All form fields will be simple label, textbox combinations in a stackpanel.
I know more detial will probably be required. Let me know what specifically you would like to know. Any help of direction is greatly appreciated.
Best,
Ryan
It sounds like you are looking for something which runtime generated, but check out the Xaml Power Toys, which will do this at design time
I see a 'Tag' property in the design view for most WinForms controls. I have never used this tag and want to know why I would want to use it.
It allows you to store some of your own data with a control. It mostly useful in tree controls where you might want each node/leaf to have some extra data associated with it. This way when you click on a node you can perform an action relevant to the node.
Its a general "catch-all" for additional data you wish to store with a control.
I too have never used it.
We perform heavy use of tags. We have some methods for checking input, and these methods checks whats in the tags in order to know what control to perform.
IE: if a textbox has RQ=1;DT=int;MAX=100
the automatic method knows that this text can not be left blank, that should accept only integers within 0 and 100.
We have a complete pseudo declarative language for this.
Kind of useful!
More specific for your question, Tags are for your use.
for example you have a lot of buttons with single method handling clicks. then at handler you have do differentiate them from each other. So you put some sort of id (or reference) and then access it there.
I have a question regarding a ComboBox in silverlight and it's selected item.
I would like to determine what triggered the SelectionChangedEvent, was it the user selecting a new item in the list or was it programatically set?
While ideally I would like to solve this using the CommandPattern (I am essentially using a modified RelayCommand (http://joshsmithonwpf.wordpress.com/2008/11/17/emulating-icommandsource-in-silverlight-2/). I am open to other suggestions.
I have also played around with the SelectionChangedEventArgs, which has an OriginalSource property, which upon first inspection may appear to help, however it is null (regardless of the manner in which the item was selected.)
Any ideas, other than setting an internal flag? :)
Thanks
Unfortunately this is a tough thing to determine, since the framework works pretty hard to simply bubble up any changes or user events in this situation as that selection changed event.
If you really need to, you could write a simple ComboBoxWrapper that is effectively the flag you're talking about - so you could derive from ComboBox, try overriding or hiding the CLR setter for SelectedItem, and then maintain state that way.
Any particular scenario in use here? There may be another way to approach a solution.