How to determine if WPF TextBox is dirty (when using UpdateSourceTrigger=LostFocus) - wpf

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.

Related

TextBox UpdateSourceTrigger = PropertyChanged - does it really affect performance?

The MSDN documentation states:
Bindings that are TwoWay or
OneWayToSource listen for changes in
the target property and propagate them
back to the source. This is known as
updating the source. Usually, these
updates happen whenever the target
property changes. This is fine for
check boxes and other simple controls,
but it is usually not appropriate for
text fields. Updating after every
keystroke can diminish performance and
it denies the user the usual
opportunity to backspace and fix
typing errors before committing to the
new value. Therefore, the default
UpdateSourceTrigger value of the Text
property is LostFocus and not
PropertyChanged.
I understand that in a situation where the update is going directly to a database, or across a network, or if it's an extremely large amount of data, that it could indeed diminish performance to use UpdateSourceTrigger = PropertyChanged on TextBoxes.
But if it is just updating a simple DependencyProperty, or a property of an Entity Framework object (prior to committing), would the performance hit not be negligible?
Just wondering, because I am creating a WPF app which tracks the state of the object being edited and optimizes the Save button appearance depending on whether changes have been made. I thought the easiest way to determine changes would be to catch the relevant SourceUpdated occurences as appropriate. It works optimally when UpdateSourceTrigger = PropertyChanged for the textboxes, as the user gets instant feedback that there are "saveable" changes.
The reason that you're warned about performance degradation is that for the most part, if you need to have the source property updated on every keystroke, it's because you need something to happen when the property's value changes. After all, if you didn't need that "something" to happen, you wouldn't really care when the property got updated, so long as it did eventually.
The real impact on performance depends entirely on what that "something" is. And that's totally dependent on your application. If that "something" is formatting and displaying the value in another TextBlock, doing it on every keystroke probably won't be noticeable. If it's filtering a 10,000-row DataTable and refreshing a DataGrid bound to it, it probably will.
So how do you tell? Well, there are two ways:
1) Understand your application. If you know what the application is doing when you update the source property, you can predict whether or not doing it on every keystroke is going to be a problem. When you say "I guess I was wondering whether it might seem to be fine at first, but can actually cause issues in certain situations I'm not aware of," what you're really saying is, "What happens if I don't know what my application is doing when the user presses a key?"
2) If you don't know what your application is doing when the user presses a key, profile it.
If it is suitable for your application and you don't notice a significant degradation in performance, then there is no problem setting the UpdateSourceTrigger to be PropertyChanged. In fact, if you're using an MVVM framework such as Caliburn.Micro, then it will set this as the default setting for all TextBoxes.

A better way of managing a forms state?

I am new to Windows programming, as in my previous work I've mostly been involved with web technologies, and mostly in the backend. I have inherited a Winforms application, and one of my biggest nightmares is navigating through the endless states a form can be in.
To give you an example, a form has the state 'New' and 'Edit' depending on whether the user decided to Add or Edit a record. On this form, we have logic. If this texbox has a certain value, then these other textboxes are disabled, etc. This leads to endless chaining of these rules. So, a textbox's TextChanged event will influence another field. It in turn will fire X event that changes the state of other controls. It quickly devolves into a tangled mess that is impossible to maintain.
There has to be a better way... something simple and elegant that solves this problem. Any suggestions?
What I do is to have a single method called FormatControls(). In this method, I implement all the logic such as myTextbox.Enabled = mycheckBox.Checked and so on.
I call this method from my event handlers in the form, such as on checked changed, etc... I also call it when appropriate (ie, form newly loaded with no data, record loaded from database, etc). This has suited me well for many years now, it makes everything less complex.
You are correct, if you do not have a pattern in use it can turn into a too-complex thing.
You can try to use tha Application.Idle event to perform the enable disable logic and insulate this part from the business logic part.
Depending on what controls you have on your form, you might be able to do away with the separate textboxes and add/delete buttons and replace the whole works with a DataGrid.

WPF Undo Redo Property System to highlight in red color if value has changed

I have a following requirement for a very complex UI. (Complex here means there are lot of controls in the form [approximately 100]). I am using MVVM (if my problem requires it to slightly go away from MVVM I am ok with it)
My question is for Editable ComboBox and TextBox. But I would say I like to hear a common algorithm which will fit all controls.
Requirement 1 : The user edits the content and goes to next control, the color of the control/text should become red.
Requirement 2 : When the user comes back to the previously edited control and enters the value which was initially present, the color of the control/text should become back to black.
I know the requirement is tough and I have been breaking my head to design a generic algorithm using which I can store the previous value and call a function to change the color of control.
To just give you all an idea, --> I tried storing 2 properties for every TextBox like Default_Text and Text. But since the number of properties are huge, the memory footprint is very huge. Also maintaining so many properties is very tough.
--> I tried adding a Dictionary to every ViewModel to store what values have got changed. But here the problem I faced was giving unique keys to all the controls in my application, which is not very helpful
--> I had even thought and tried about subclassing controls like TextBox, ComboBox and overriding some methods to suit my requirement, but sadly I failed miserabley when I started adding validations and all.
So here I am stuck with designing a generic WPF property system/algorithm to handle all undo redo functionality, changing styles of controls,etc!!!
It will be really great if you experts can guide me in right direction and also help me in developing such an algorithm/system. A sample illustration will be nice though!!!
I found an answer to the above problem. I used attached behavior for this. More details on this link Function call from XAML from StackOverFlow.
When I databind, I store the initial value of the DataBound variable in the Tag property by using Binding=OneWay. Then I have written a attached behaviour for LostFocus event. Whenever the user enters a control and then goes to other control, it fires LostFocus event and calls my attached behaviour. In this, I check whether the value is equal to the value in Tag. If it is same, I display in black else I display in red.
Attached Behaviour rocks in WPF. I can achieve anything from that cleanly without code cluttering!!!!
Another alternative is to use some "dirty" tracking in your models (or viewmodels) and bind to a properties isdirty (and convert it to a color).

Should the MVVM ViewModel perform type conversion/validation?

We're just getting into MVVM in WPF.
We have implemented our ViewModels with 'strongly typed' properties (int, double? etc.) that we bind to in the view.
Type conversion works OK, mostly, and so entering data is simple enough. But we run into problems with validation.
If, say, a non-numeric value is entered in a text box bound to a numeric property, the conversion fails, the property is never set, and we never get a chance to provide proper feedback to the user. Worse, the property retains its current value, leading to a mismatch between what's displayed in the view and what's actually in the ViewModel.
All this can be handled with value converters, I know. But I have seen several opinions to the effect that conversion should not be the view's responsibility at all. What is entered in the view are strings, and the conversion, validation etc. should be the ViewModel's responsibility (so the argument goes).
If so, we should rewrite most of the properties on our ViewModels to string, and provide error information through the IErrorInfo interface, for example. It would surely make for simpler, leaner XAML in the view. On the other hand, conversion, validation etc. will be less declarative, explicit and flexible, from the point of view of the View designer.
It seems to us these two approaches are fundamentally different, so before we decide, we'd like some informed SO opinions on the matter.
So: should ViewModels expose a simplified, 'text-based' interface to the view and handle conversion internally? Or should ViewModel properties expose the actual data types, leaving such chores to the view to handle?
Update:
Hard to pick a winner here, but I finally landed on one of you who concludes more or less like myself.
Specifically, we have decided to keep the ViewModel properties typed. The main reason for this is the flexibility it affords us in the design of the view, and the power of explicit, declarative conversion/formatting in XAML.
I noticed an assumption with you who will disagree with us in this, that the design of the view is fixed and ready. Hence, no decisions about conversion, formatting etc. need be made in the view. But ours is an agile process, and we haven't got all the nitty gritty detail of the UI figured out on beforehand.
In fact, leaving the details of the UI to be worked out along the way leaves room for creativity and besides, in my opinion, even a meticulously worked out design will always end up morphing throughout the implementation process.
The point of all this is that whereas business rules enforcement certainly belongs in the ViewModel, it seems to us that simple conversion and formatting is a view-thing. It may sound like heresy, but I don't actually think type conversion in the view needs unit testing at all (so long av we unit test the actual type converters).
All in all a great discussion, folks, with well formulated, informed opinions. Thanks.
This is a very interesting question and one that I don't feel has a definitive answer, but I'll do my best to throw my thoughts out there.
Looking at the MVVM pattern as I understand it, the point of the ViewModel is to expose the data in a way the View can understand without any assumptions about the way the view is going to use it. For an example let's pretend that we are modelling the speed of a car:
public class CarModel
{
public int MilesPerHour { get; set; }
}
public class CarViewModel
{
private CarModel _model;
public int MilesPerHour
{
get { return _model.MilesPerHour; }
set { _model.MilesPerHour = value; }
}
}
In the example above I've exposed the property as an int since that is what it is in the model. The disadvantages of this you have listed in your question, but the main advantage is that it gives the creator of the view a valuable piece of information about how to display that data. Remember that we (as the authors of the ViewModel) don't know what the View looks like. By committing to the idea of the data being an int the View can use a textbox or some other control that only accepts numbers (a dial, for example) to display the information. If we say that we are going to format the data in a way that we assume is helpful to the View it takes that important power away from it.
On the other hand we work in real world. We tend to know what the view is. We rarely plug and play different views on top of the same ViewModel and adding the conversion code into the ViewModel is simply easier. I don't think it is right, but that doesn't mean you won't find my production code using it...
Finally (and I'm sure you know this, but for completions sake...) business logic should be done in the ViewModel. If we decide that the car shouldn't go above 70mph then it isn't the responsibility of the view to enforce that. So you'll still end up with some kind of error provider, but at a business rather than display level.
Okay, maybe that wasn't finally....
I wanted to address the comments made by Kent, and my thoughts didn't fit into a comment.
Obviously the primary difference between my and Kent's point of view (as I understand it) is he reads ViewModel to be a Model of the View and I read it to be the thing that exposes the Model to the View. A subtle difference I'll admit, but I think the upshot is that I don't want to remove information that the model provides, even if it makes it easier for the specific view I'm using.
My point of view is based on the assumption that you should be able to swap views out, they should be fleeting things that may change depending on the requirements of screen size, hardware, platform, latency and environment. The interesting twist is that I have never actually needed this functionality, nor seen anything (beyond proof of concept applications) that have ever used it, but if we accept that we won't use it now or at any point in the future, and that each ViewModel will work with one, and only one, View then we may as well go back to putting all the code in the code-behind file and throw the ViewModel out completely - after all, it's so tightly coupled that it may as well be the same class.
Ideally I would like a situation where the ViewModel can say "this value is an int, it will always be an int, and you can display it in anyway that you like. But you can give anything back to me and I'll do my best to make it fit, and if I can't I'll let you know". Basically my MilesPerHour property should have an int getter, but an object setter. That way the views keep all the information I feel they need, but don't have to worry about conversions or validation.
Absolutely it belongs in the view model, for all the usual reasons, including:
Designers own the XAML. Do you want the designers to have to understand and implement the requisite type conversion and validation logic?
Testability. Don't you want to validate that your conversion and validation logic is working correctly? It's much harder if it's embedded in the view.
On the other hand, conversion, validation etc. will be less declarative, explicit and flexible, from the point of view of the View designer
I think this is a moot point because the view designer should be responsible for these things. The designer is trying to make the UI look and feel a certain way; it is the developer who implements the business logic, including conversion and validation logic.
Should the MVVM ViewModel perform type
conversion/validation?
Yes.
The view model is an abstraction layer between the view and the model - the perfect spot to perform any type conversions (instead of cumbersome value converters). Validation should absolutely occur as part of the view model.
We use our View Model to handle the conversions as much as possible for data types. This reduces the need for a value converter to some very specific circumstances. You want to expose whatever type is easiest for the view to consume. This has been working well.
The one specific question you raised:
If, say, a non-numeric value is
entered in a text box bound to a
numeric property, the conversion
fails, the property is never set, and
we never get a chance to provide
proper feedback to the user. Worse,
the property retains its current
value, leading to a mismatch between
what's displayed in the view and
what's actually in the ViewModel.
might be handled by exposing your view model type as a nullable type. This should still allow the underlying source to be updated, even if invalid data is entered, and trigger validation. This worked in a similar situation we had with DateTime and a date time picker.
Keep the view as dumb. We don't have official designers, our developers are our designers, so keeping the view dumb has some benefits:
We (developers) get to keep our sanity (XAML is somewhat less verbose)
Business logic (including validation) stays in the view model and can enable testing
Good Luck!
-Z
This is a good question, and I can certainly see both sides of the discussion.
My thought is that what you're really looking for is a proper NumericInputControl that you can use in your xaml. This will provide a better user experience because your users won't be able to accidentally enter text in a number field and, because the control constrains input without validating it, you can maintain the more strongly-typed ViewModel.
I'm not sure how you'd want to go about implementing one, I know that the classic spinner/NumericUpDown controls are falling out of favor because they aren't touch-friendly, but I don't believe that the introduction of such a control will violate the purity of the design approach or your ViewModels. You'll receive a number that you can then range-validate in the appropriate place, supply feedback via IDataErrorInfo as usual, and so forth. :) This technique lets you get the best of both worlds without any real drawbacks (except the creation of a numeric control).
Or should ViewModel properties expose the actual data types, leaving such chores to the view to handle?
Conversion and templates are done in View, because they both are just a conversion of values, models and viewmodels into controls! Controls are available only inside View.
Validation is done in ViewModel, because validation is done according to business rules and can even be done through a call to a remote service. View knows nothing about business rules, but knows how to present validation results.
If, say, a non-numeric value is entered in a text box bound to a numeric property
A properly crafted numeric text box control never allows user to input a non-numeric value.

How do I Determine the Source of the SelectionChangedEvent

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.

Resources