how can i track the number of undo operation of a wpf richtextbox?
You can't do that. Undo logic is private inside TextBoxBase class and it depends on internal UndoManager class. I advise you not to hack with Reflection, because your code can break if MS decides to change implementation, but if you decide to do it anyway, you can use Reflector to get code of TextBoxBase.CanUndo property to understand how it works. Number of available undo operations is probably in the UndoManager.UndoCount property, but there's additional logic you need to consider.
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.
Advance apologies for the event-style explanation; there's a lot of factors that I feel all play a role of their own. WPF is not my native framework of choice, and it probably shows. :)
Old situation: I had a window with several controls. Depending on their selections, I used multibindings and a converter to determine whether certain controls needed to be shown that inform the user about the implications of their changes before they'd eventually confirm them by OK (or simply dismissed by using Cancel). This worked perfectly.
Problem: Too many controls as time went by, too much clutter.
Solution: Put stuff in different Pages so it becomes easier to browse for the user. In order to have changes-to-be persist as a user arbitrarily browses between the pages, I create these dynamically and put them in a cache (Dictionary<string, BasePage>, see below), from which they will be pulled as the user chooses them.
Consequence: I need to decouple the bindings to the notification controls as the different options are now on different pages.
Solution? I put a BasePage class in that exposes certain abstract read-only properties that define the various aspects that the window needs to know about in order to do its notifications. For example, a bool requiresReboot property defines whether the current state of things on that page requires a reboot to take (full) effect. A specific page implements the property based on its controls.
Problem: I do not know how to keep create a proper binding that properly gets updated as the pages are changed. I tried giving my notification controls a binding to the Dictionary<string, BasePage> with a converter that checks all pages and the relevant property.
Questions:
1) How do I create a proper property for this purpose? I presume I need a DependancyProperty as I did a fair bit of reading on MSDN, but I can't figure out how this fits together.
2) How do I make a link between my custom property so that it allows (multiple) control(s) on a page to change that property? Do I use INotifyPropertyChanged somehow? My old example bound against several CheckBox.IsChecked properties in XAML. I am trying to avoid putting tons of events (OnChange, etc) on the controls as the original code did not need it and I have been told it makes for a messy solution for as far WPF is concerned.
3) Finally, I suspect I may need to change my Dictionary<string, BasePage> class to a custom implementation that implements some sort of INotifyPropertyChanged but for Collections? Observable Collection is the term I am looking for, I believe.
I hope someone is able to bridge the gap in my understanding of WPF (property) internals; I would very much appreciate it. A basic sample would be even better, but if it is too complicated, just a nudge in the right direction will do. Thank you. :)
It's been a while since I solved this, and while I cannot remember the exact cause of the problems, there were a few different issues that made up the bulk of the trouble I ran into.
I ended up making the Property in question a non-abstract DependencyProperty in the base class; it was the only way in which I could properly delegate the change notifications to the interface. Derived classes simply ended up binding it to their controls (with a proper Converter in the case extra logic was necessitated).
As Dictionary<string, BasePage> does not support any sort of change notification, I made an extra collection of ObservableCollection<BasePage> which I used for binding purposes.
However, such a collection does not propagate a change event when items inside of it has a property changed. Since this situation required that, and I was binding to the collection itself in the context of a property that does not have a Master<->Detail relationship like a DataGrid (which basically add their own OnPropertyChanged handlers to the binded object), I ended up subclassing a VeryObservableCollecton<>. This one listens to its own items, and throws a proper change event (I think it was an OnPropertyChanged from the INotifyPropertyChanged interface) so that the binding (or in this case a multi-binding) would refresh properly and allow my interface to update.
It is hardly the prettiest code, and it feels over-engineered, but at least it allows me to properly bind the UI to the data in this manner.
I know this has been done to death, but most answers are along the lines of "yeah, you can use eventhandlers in place of commands if you like". This still doesn't solve the problem of whether writing complicated commands is warranted vs just wiring up eventhandlers in code behind to call testable methods in your view model.
I don't like commands because they produce a lot of boilerplate code and don't give me any benefit over normal methods, plus some of them (such as drag & drop) are a pain to implement.
What's wrong with writing:
codebehind:
private void Button_Click(object sender, RoutedEventArgs e)
{
viewModel.LoadData();
}
viewmodel:
public void LoadData()
{
//....
}
This is equally testable (if not more) as any command is. IMO, as long as UI specific stuff isn't leaking into your business logic, there's really no need to waste time on complicated patterns like that. Thoughts?
What's wrong with writing
Nothing - for the most part.
There is nothing wrong with using code behind, if you are careful to keep the business logic out of the code behind file. This is delegating this directly to the ViewModel, which is reasonable.
That being said, there are a couple of potential downfalls here in terms of long term maintainability:
By doing this, you're coupling the View to the ViewModel more tightly. While this is a reasonable thing to do (the View, in reality, always knows about the ViewModel), it does prevent potential reuse of View components in some scenarios, as using an ICommand allows you to have the same View be used with potentially different ViewModels. (This is rare in practice, however.)
This starts a slippery slope - by adding "any" code into code behind, you're opening up the potential that another developer will add "just one more line" in there. Over time, this can lead to a mess.
It's adding code into another place that has to be maintained. Now you'll have to maintain the ViewModel .cs file, your .xaml file, and the code behind file.
You're hard-wiring this logic into a Button. If you decide to change controls, use a gesture, etc., you'll have to remember to rework this logic.
I was in your boat at first, I even asked basically the same question here. But I came around and came to really like commands.
Some commands really are complex enough in and of themselves to warrant testing. They are just as testable as anything else on your viewmodel.
ICommand also includes CanExecute and CanExecuteChanged, which enables your view to intelligently enable/disable itself pretty much for free. This is fantastic in complex views.
Commands make it easier to change your view around, most controls have a Command property you can bind to, and simply moving the binding around is easier than mucking with event handlers. This is especially true if you have designers working on the XAML.
You can pretty much write the entire logic of the view without the view even existing. It leads to a nice flow of build the meat all at once, then throw the interface on top all at once.
Keeping your code in one place leads to longer term maintainability.
To me a very important argument against events is forcing the UI Designer to write code to be able to test a View. And worse: every time he redesigns the View he has to rewire the events.
Commands and the behaviors in Blend make render this process obsolete and much easier.
Another problem might arise when actually using the event arguments when writing the event handler. When you want to switch to another control or another event you might have become very dependent on the event arguments making it hard to switch because the other control/event does not support the same event arguments.
I'm having trouble deciding what to think about this piece of code:
public SolidColorBrush Brush
{
get { return IsValid ? _validItemBrush : _invalidItemBrush; }
}
It is part of a view model in my current project and as you can imagine, the Brush will be bound to some text elements in the UI, to indicate (in-)validity of other pieces of data, in an otherwise fairly simple and straightforward dialog.
The proponents of this piece of code say that since we're using WPF, we might as well allow for some simple WPF specific constructs in the view model.
The opponents say that this violates Separation of Concerns, as it clearly dictates style which should be taken care of solely by the view.
Please share your arguments, and if you're not happy with the code above, please share your ideas around alternative solutions. (I'm particularly interested in what you have to say about using DataTemplates).
Is it possible that there is one solution that could be considered best practice?
Personally, I would have the two brushes be defined in XAML, and have the controls that use them switch brushes (in xaml) based on the IsValid property. This could be done very easily with DataTriggers, or even a single IValueConverter - the converter could take 2 brushes and a boolean and swap between them fairly easily.
This keeps the business logic presentation-neutral - a "Brush" is very specific to a specific form of presentation, and a pure View choice. Hard-coding this into the ViewModel violates the single responsibility principle as well as is not a clean separation of concerns.
I would very much keep this in the View, and switch based on the IsValid (bound) property that is ViewModel specific.
While there are circumstances where I might use WPF constructs in the view model, this isn't one of them. Here's why:
It's harder to change. If you define brushes as resources and use them in styles, changing your application's color scheme can simply be a matter of loading a different resource dictionary. If you hard-code color values in your view models, you have a lot of different things to change if it turns out your end users need different colors.
It's harder to test. If you want to write a unit test that checks to see if a property is returning the right brush, you have to create a brush in your unit test and compare the values of the two, since it's a reference type.
In many, maybe even most cases, it doesn't make the code simpler or easier to maintain. You're pretty likely to already be using a style (assuming that you are conversant with styles), since they make just about everything in WPF easier. Binding IsValid to brush colors is just a matter of adding a DataTrigger to a style. Which is where anyone maintaining this code would expect to find it.
There are certainly times when I do use WPF constructs in the view model - for instance, long ago stopped wondering if it was problem if a view model exposed a property of type Visibility. Note that none of the above concerns apply to that case.
In cases like yours where it's purely aesthetic I use Triggers or the Visual State Manager to change colors.
Sometimes I do use colors in my ViewModels, but only if its part of my software spec (e.g., the color of the chart displaying a patient's CO2 depends on localization). In that case, I use a Color struct bound property, allowing the View to use the Color for a SolidColorBrush, a GradientStop, or whatever it wants. I initially used a string in #AARRGGBB format to completely remove the WPF dependency but my more seasoned co-workers didn't like that.
Ok,
So I have been stalled in my latest non-work project, trying to use WPF. I am just frankly annoyed at databinding. I thought it was supposed to make things simpler by binding data directly to the UI. But the more I learn about having to implement INotifyPropertyChanged to get things to notify the UI if they changed, seems to make the whole thing counter productive.
Am I missing something? It seems like a bunch of work and having to make the classes implemented INotifyPropertyChanged seems like a fishy way to get databinding to work.
What am I missing? I must be missing something. Please enlighten me into how to make databinding easy, or at the least straightforward.
If you want the UI be notified when the underlying data source changes, then you need some sort of notification mechanism. For WPF, INotifyPropertyChanged is that mechanism.
It's the same in Windows Forms as well, but Windows Forms also supports the old notification mechanism, where you have an event with the name <Property>Changed.
However, neither of these required these mechanisms if all you want to do is bind to the data once and display it.
If you are ok with not receiving notifications, then just bind to the data source and it will work.
Truth be told, I haven't seen that it was that bad, and think it a highly workable solution.
Take this simple, Data Model object:
Public Class SimpleItemViewModel
Implements INotifyPropertyChanged
Private _item As String
Public Property Item As String
Get
return _item
End Get
Set (value as string)
_item = value : OnPropertyChanged("Item")
End Set
End Property
Protected Overridable Sub OnPropertyChanged(propChange as string)
Raise Event PropertChanged(me, new PropertyChangedEventArgs(propChange))
End Sub
Public Event PropertyChanged(sender as object, e as PropertyChangedEventArgs)
End Class
That is easily bound to a simple Textbox via:
<Textbox Text="{Binding Item}" />
additionally, if I wanted to have a DIRTY flag, I can easily put the flag being set in the OnPropertyChanged sub, and easily determine if I need to save any user changes or not.
I have found it easiest to have a set of classes which rest between the Data Access layer and the UI which holds this stuff. You can even have your Business Logic and DAL pass these classes around rather than the atomic values.
Implementing INotifyProperty changed is not particularly difficult, seeing as it only has one member.
If you don't expect changes in the underlying object then don't worry about INotifyProperty changed, and use a Binding with Mode=OneTime.
If the underlying object can change and you want the GUI to reflect those changes, then how else can this be achieved without the kind of notification that INotifyProperty changed provides? It's not reasonable to expect a bound item to poll its binding's source.
Personally I've found WPF has taken some time to get to grips with, but now that I'm gaining comfort I'm finding it incredibly powerful and enjoyable to work with. I encourage anyone who's finding WPF challenging to stick with it.
Binding in XAML is quite easy, however, dynamic WPF data binding in code is painful and confusing.
DataBinding is the only way to implement a model-view pattern in WPF/Silverlight. Your models can be UI-stupid by implementing INotifyPropertyChanged, which isolates them from the UI. It also saves a lot of UI code when stuffing information into the UI.
Another benefit that I enjoy is the ability to further bind child controls with the same data by using the { Binding } shortcut.
First, INotifyPropertyChanged isn't the only way to get data binding to work - dependency properties work too.
Second, INotifyPropertyChanged can be implemented with just one line of code in your entity class, if you use AOP - you don't actually have to do all those notification calls yourself.
Overall, I'd say data binding is a great boon, especially when you're doing code generation to make automatically bound controls from some data source.
If you're looking for a good way to think about structuring your data binding, then aim to set a DataContext on your logical tree only once, then use binding paths to populate the various parts of your UI.
Be as declarative as you can in your binding. Let the template system do it's job and make heavy use of DataTemplates that specify explicit DataTypes.