The documentation I've found for WPF's INotifyDataErrorInfo seems to state that the GetErrors() method is called when either a value is set through the UI, or as a result of the INotifyDataErrorInfo's ErrorsChanged event having been called.
But that doesn't match what I'm seeing when debugging a window whose DataContext is a viewmodel that implements INotifyDataErrorInfo (the viewmodel in question is built on Mvvm Light).
Instead, GetErrors() is called when the window is initialized and its DataContext is set, but afterwards only when the viewmodel code raises the ErrorsChanged event. Which in my case it does whenever certain properties are set in the viewmodel, by code I've written to raise the ErrorsChanged event.
I'm asking this question because I want to know if I need to handle the situation where GetErrors() might get called by WPF without me first having called the validation code. That could erroneously report that no errors exist, when in fact that's only the case because validation hasn't taken place yet.
It's called when errorschanged is raised.
I just experimented with a sample I have. This thing: https://gallery.technet.microsoft.com/scriptcenter/WPF-Entity-Framework-MVVM-78cdc204
I put a break point in the geterrors method of my base class and spun it up.
Geterrors was not called until I made something invalid.
If you see different behaviour then it's something you are doing differently.
Related
I'm trying to understand how WPF implements the routed commands which, internally, are themselves implemented by routed events. In the UIElement class definition, we find this piece of code:
EventManager.RegisterClassHandler(type, CommandDevice.CommandDeviceEvent, new
CommandDeviceEventHandler(UIElement.OnCommandDeviceThunk), false);
From there on, the UIElement.OnCommandDeviceThunk handler will pass along all the information through arguments of functions it calls in its body which themselves do the same until it reaches the CommandBinding.Executed event which we subscribe to, thus executing our response code.
What I can't seem to find, and would like to understand, is who raises the CommandDevice.CommandDeviceEvent?
When, for example, I have linked a ButtonBase subclass object's Command property to an ApplicationCommands command, does it raise the CommandDeviceEvent in some way and how does it do it?
I understand the GlobalEventManager holds scores of lists of event handlers, but I haven't yet understood who raises the events to trigger those handlers?
When, for example, I have linked a ButtonBase subclass object's Command property to an ApplicationCommands command, does it raise the CommandDeviceEvent in some way and how does it do it?
The ButtonBase class calls the ExecuteCommandSource method of an internal CommandHelpers class when it is clicked: https://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Controls/Primitives/ButtonBase.cs,c0949dd81fca07f3,references
This method then executes the actual command, i.e. the object that the ICommand property returns: https://referencesource.microsoft.com/#PresentationFramework/Framework/MS/Internal/Commands/CommandHelpers.cs,518e4547841e704d
I have a WPF window that takes a few parameters in it's constructor. I then use these constructors to setup the state of the window. Part of that constructor process is instantiating my view model class that is then set as the windows DataContext.
My question is when should I set my DataContext equal to my view model object-- before or after the call to InitializeComponent()?
I ask because if I set it beforehand, I then need to manually launch code that is executed after the window has been initialized, because certain events should fire when the DataContext is assigned, or re-assigned.
It is my assumption that there shouldn't be any binding issues if I set the DataContext after the call to InitializeComponent() but I wanted to ask for advice on the matter before making the final call to wire up my window this way. Could I be missing something the could come back to haunt me if I set my DataContext after the call to InitializeComponent()?
My question is when should I set my DataContext equal to my view model object-- before or after the call to InitializeComponent()?
It shouldn't matter unless you rely on some bindings that are established during the call to the InitializeComponent(), like ElementName bindings:
Cannot bind ItemsSource to ElementName
The InitializeComponent() method itself locates a URI to the compiled XAML file and passes it to a LoadComponent() method that parses the BAML, i.e. the compiled XAML, and creates instances of the elements that you have defined in your XAML markup:
What is the connection between .xaml and .xaml.cs files
Simply setting the DataContext property of the window to an instance of a view model class that elements in the view bind to might as well be done after the call to the InitializeComponent() method. These bindings aren't resolved before the constructor returns anyway.
Here's my addition to #mm8's answer:
Usually it does not matter, but set DataContext after InitializeComponents. When DataContextChanged event is called, you naturally expect, that components are already initialized.
Also it's good to know whether the components can be initialized without DataContext and separate possible initialization issues from binding issues. If you set DataContext before InitializeComponents, the binding issues may result in an exception in InitializeComponents.
Make you ViewModel constructor very fast. Don't do any DB calls or any I/O calls, etc. You want to display the UI as soon as possible.
Make sure your ViewModel constructor never throws an exception. Parameter validations is OK, but just for debugging purposes. It should never happen in production.
If you need to load data into viewmodel, create separate async method called e.g. Activate(), which you will call from View's Loaded or OnNavigatedTo event.
Additionally, if you subscribe to some events in ViewModel, you should unsubscribe. Ideal place for subscription is Activate method, resp Deactivate to unsubscribe. If you subscribe in ViewModel's ctor, it may happen that Activate/Deactivate will never be called and you introduced memory leak.
If you feel your bindings are slowing the UI, try to use {Binding IsAsync=True}, resp x:Bind, or try to use codebehind to set the properties in worst case.
Different from what you ask, I suggest two changes:
Set the DataContext of an inner element and not on the Window / UserControl itself.
Set the DataContext on Loaded instead of the constructor.
These points are more obvious when looking at a UserControl, which will probably be embedded at multiple points, but remember that a Window can be created by explicit startup code instead of some App.StartupUri.
Regarding the first point, consider the OOP design basics. Forget about WPF / XAML specifics and remember that you derive from a Window class and create a subclass of it. The contract of this class includes a public get/set property named DataContext which accepts any kind of object. So you should at least think about, how bad you will screw up, if someone is replacing your DataContext from the outside. When you instead set the DataContext on the next-inner FrameworkElement inside the window, it is hosted in an environment that is owned by the window.
Setting the DataContext on Loaded is working for me, while I ran into problems with constructor time setting. However, I can't actually recall the details of it, maybe it was related to the visual designer (that I'm not using anymore). For other controls it is easier to explain: constructor time initialization sucks when hosted in a virtualizing panel, also property initializers (new MyControl { Prop = Value }, XAML property assignments, ...) are not handled by time the constructor runs, so objects tend to be in a different state than how they are presented later.
When should I use the Command and when to use the Click event?
F.e. if I have a Button in my UWP app what should I use?
When should I use the Command and when to use the Click event?
Yours is a broad question and I would simply answer with: "It depends".
Because:
The Command implements the ICommand interface and this means more code to add to your application but usually this won't change. Instead, the event handler doesn't require any interface implementation.
For every command you want, you have to provide the code that will handle the click and the CanExecute logic, to say when the command can execute. This is not requested in a simple event handler (like MyButton_Click). This means that, using a Command, you will have more control over the elements of your UI (the button won't execute anything if CanExecute is false).
When you want to add a Command, you will bind it to your DataContext (the ViewModel, if you implement the MVVM pattern). Instead, when you add a simple event handler (like MyButton_Click), the code will be placed in your code-behind that is the logic behind your main window. This means that implementing a Command, according to me, you'll have everything you need to modify in just one place (the ViewModel) instead of logic scattered everywhere in your project.
Of course, you can use whatever you want and my points are there just to give you an insight about these different implementations and you have to consider which solution is suitable for you, considering also the requirements you have been given (like: "Don't use event handlers" or "The Command is too advanced, let's just use something simple", etc.) and/or other constraints in your project.
I'm trying to perform some actions at my VM just before my Window closes, It mean I need DataContext must be available for my actions.
Actually I'm trying with this:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding _MyCleanUpCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
But, at this point all objects on my ViewModel are cleaned and my DataContext = null
What is the propper event to Bind with my command?
There is a way to force one class to execute Automatically a method when this is no needed anymore (Needed mean in my current proccess)?
NOTE: For the second question IDisposable does'nt work due must be called manually. ~ Finalizers doesn´t work inmediatelly.
First of all the objects are not being cleaned.
The name of the event you are trying to listen to is called "Closing" which is being fired before the actual close. The event that signals to you that a window got completely closed is called "Closed". Those are the two events available for you.
I would simply associate the handler in the View constructor
MyWindow()
{
// Set up ViewModel, assign to DataContext etc.
Closing += viewModel.OnWindowClosing;
}
Then add the handler to the ViewModel:
public void OnWindowClosing(object sender, CancelEventArgs e)
{
// Handle closing logic, set e.Cancel as needed
}
In your case, you gain exactly nothing except complexity by using a more elaborate pattern with more indirection (5 extra lines of XML plus command pattern).
The "zero code-behind" mantra is not the goal in itself, the point is do decouple ViewModel from the View. Even when the event is bound in code-behind of the View, the ViewModel does not depend on the View and the closing logic can be unit-tested.
However if you insist on sticking to interaction I recommend you read this link below:
http://msdn.microsoft.com/en-us/library/ms748948.aspx
It will give you an overview about events of Window.
Btw, like I already said DataContext is there for sure so I assume you rather have a bug somewhere in Command pattern (you might have defined the Command wrong). You should have posted us the complete code.
Futhermore giving names to public commands with first letter being an underscore is sooo outdated. I remember using them 20 years ago in pure C to signal a private field. :)
Your DataContext and all other objects shouldn't be already cleaned when you enter into your Closing command. This is not the expected behavior.
Indeed, the main purpose of the Closing event is to provide a way of preventing the application exit without any harm (from msdn):
When a window closes, it raises two events: Closing and Closed.
Closing is raised before the window closes, and it provides a
mechanism by which window closure can be prevented. One common reason
to prevent window closure is if window content contains modified data.
In this situation, the Closing event can be handled to determine
whether data is dirty and, if so, to ask the user whether to either
continue closing the window without saving the data or to cancel
window closure. The following example shows the key aspects of
handling Closing.
Chances are there's a bug with your EventTrigger which triggers the associated command too late in this particular scenario.
Try to simply bind your window to the Closing event in code behind and see what happens.
I have a User Control that contains a list of items and I raise an event when the currentIndex changes, also, when it changes, I must call two other methods two verify and change the appearance of the Control (change an Image and block/unblock some buttons).
What I want to know, mostly out of curiosity because it is already working, is when is it more appropriate to call these two methods?
Should I call them within the CurrentIndex property per se? Should I call them within the OnCurrentIndexChanged(...)? Should I handle the event within the class and do it there?
I'll assume you've implemented the standard event generating pattern and made OnCurrentIndexChanged protected virtual so that a derived class can override the method and alter the event generation and/or handling.
Unfortunately that requires reading tea leaves, why would anybody want to override the method? And more seriously, how could overriding the method break your control when they do? That's awfully hard to guess at for anybody that doesn't know the code well, not exactly easy for you either. The principle to apply here, used in the .NET framework code as well, is to do as little as possible. Just raise the event, nothing else. Which minimizes the odds of breakage when the derived class does something silly, but entirely common, like not calling base.OnCurrentIndexChanged.
The behavior of your controls is an implementation detail of your UserControl. So change their properties in your CurrentIndex property setter, then call OnCurrentIndexChanged(). Anybody that derives from your class can override that behavior, if necessary. And nothing goes wrong when they forget to call your OnCurrentIndexChanged() method. But do note that you need to make the control variables protected instead of private. So they can override the behavior, if they need to.
And don't hesitate to just not use a virtual method at all if this is too spooky for you. It's not common to have to accommodate hundreds of thousands of programmers with your controls :)
In the user control, I would have a property that represents the selected item. Then, during the setter of the object, raise the event method to change your user control. That way, in the future, if you need to add more listeners, you just need to add another handler in the setter method. This is pretty common in MVVM applications and is pretty maintainable.
Because your UserControl acts as a ListControl, you need to implement two events and two properties.
public event System.EventHandler SelectedIndexChanged;
public event System.EventHandler SelectionChangeCommitted;
public int SelectedIndex {
get;
set;
}
public T SelectedItem { // Where T is whatever your type is
get;
set;
}
SelectedIndexChanged should always be used for actions that always need to be triggered when your selected index is changed. SelectionChangeCommitted should only be triggered when the user physically changes the selection. The separation between the two is an important distinction, and most controls in .NET follow this pattern (eg. ComboBox), but may not use the same name for the events.
Now, with that said, if the controls you need to change properties for are also within the same user control, then you should of course handle that within the user control code in the appropriate event. Otherwise, the code should be orphaned to whoever implements the user control (eg. a form or another user control) by subscribing to the event and doing the work there.
The order really depends on your requirements, but SelectedIndexChanged should always be raised (but not more than once per change as that would introduce strange behavior), and again SelectionChangeCommitted should only be raised by the user (eg. setting SelectedIndex or SelectedItem).
A good rule of thumb is if your internal stuff MUST happen before the user knows about it, call SelectedIndexChanged first, then SelectionChangeCommitted. If it doesn't matter, either or. Changing the order later on could result in breaking changes in whoever implements the control, so make sure your decision is solid.
The difference between the two is SelectedIndex and SelectedItem would be updated by things like clearing your list internally, adding new items, et cetera, but does not necessarily mean it was a physical user action that should result in both your events firing.
Hope this helps.