I have several textboxes on my view. One of them needs to get focus. Which one exactly is defined in the data model. Currently I call the Focus method right after binding is done. I get false as a result which means the focus cannot be set. Question is
what is right time for doing this?
how do I know this moment being in the view model without knowing about the view anything?
The right answer is to schedule setting the focus via Dispatcher.BeginInvoke. It means the view model has to have a reference to the Dispatcher object which is somewhat tricky to do but worth the effort.
Related
I'm starting on my first WPF project using MVVM and Castle Windsor. I'm following the fairly standard approach of injecting a view model into its view's constructor, which then sets its DataContext to the view model. What I'm not clear on is how/where to perform any UI "initialisation" that I want to happen right after the window has loaded (in my case I want to instantiate a number of user control "widgets" and put them on the window's canvas).
Presumably I can't do this in the constructor of the window's view model, as it will have been called prior to the view's InitialiseComponent being called. Besides, how would I even reference the canvas from the view model, which should have no knowledge of the view?
As part of trying to solve this, I created a "DesktopManager" component responsible for adding user controls to the canvas, but I'm getting circular references:-
the view obviously has a dependency on the view model
the DesktopManager has a dependency on the view (it needs to access the Canvas),
the view model has a dependency on the DesktopManager (so it can tell the DesktopManager to create the widgets).
The DesktopManager still won't help me though - referring back to my earlier question I don't know how/where to call it to create the widgets. I'm clearly going about all this the wrong way, and perhaps answering my earlier question will solve this one too!
Any suggestions appreciated.
Andrew
If you are looking for a way to execute code in your view model once the view has been loaded, I would suggest that you bind the Loaded event of the view to a command in your view model.
Look here for one way to bind events to commands:
http://www.danharman.net/2011/08/05/binding-wpf-events-to-mvvm-viewmodel-commands/
I am using observable collections all around my applications. My problem is that when i use a popup window for editing those entities, my bound lists are getting changed when the user changes those corresponding fields in the window.
How could i simply freeze the observable changes norifications, and release them only when the entity is saved?
Thanks,
Oran
I think the issue is not with the collection, but with the entities themselves. ObservableCollection raises an event when an item is added or removed, not when a property of an item is changed. This part is handled by the INotifyPropertyChanged implemented by the item, so it's this notification you need to disable.
I suggest you have a look at the IEditableObject interface, which is designed for this kind of scenario. You can disable the notifications in the BeginEdit method, and reenable them in EndEdit and CancelEdit.
EDIT: Paul Stovell has a nice implementation of an IEditableObject wrapper here :
http://www.paulstovell.com/editable-object-adapter
You can use:
BoundPropertyOfViewModel = CollectionViewSource.GetDefaultView(AgentDeploymentDetail);
and bind to the view instead of binding directly to the ObservableCollection. This is the same object that allow you to filter/sort your output without touching the collection.
When you want to stop changes, use DeferRefresh(). When you are done, call Refresh().
WARNING
This will not pervent showing of changes in each item itself, only the list.
You could make a deep copy of the object you want to edit. This way, you can act on the copy while editing, without interfering with the original that remains in the list. Once you`re done editing, you can replace the original by the edited version or rollback.
All the anwers above are great. but i found a good and convinent prodedure to perform the desired in an efficient and clean way. It is based on performing a deep copy on a detached object, using Matthieu MEZIL entity cloner ( http://msmvps.com/blogs/matthieu/archive/2008/05/31/entity-cloner.aspx ).
For full details please check out the followings : Entity Framework Attach Exception After Clone
Thanks for all the great support...
Like the title says I am trying to architecture into my application a way to distinguish the source of a variable change, either from UI or code-behind.
My problem is that I need to trigger some action after a property changed its value, but I only need to do this when the change comes from the UI because otherwise I don-t want to perform that action. I am having some trouble because, for example when a checkbox(two way binding), changes state, my binded property gets updated and then I use the checked and uncheked events to trigger that action.The problem is that when I change the property in codebehind it also triggers those events and I do not want that. Right now, i am using a flag that enables, or not, the actions at the event handlers but I do not feel that this is a good idea.
Any sugestions or ideas?
I am considering using only one-way binding and control everything my self, using commands.
It looks like you have some confusion between your model and your controller. There shouldn't be any cases where it matters if the a change to the model comes from the user or not. If you want to have something like a confirm message it the user makes the change, then don't bind the view control directly to the model, but have the controller respond to the event.
That way, if the control is changed to be the same as the model, then the change is internal, and no confirm is required, but if the control is changed by the user, then the control state differs from the model, and a confirm can be shown.
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.
I'm working in WPF using the MVVM pattern, and generally things seem to be working pretty well, as I wrap my brain around the nuances of both WPF and MVVM. However, I'm currently stuck on a particular issue. My actual application is fairly complex, so to simplify, let's take Josh Smith's near-defining article on the pattern and use the application therein.
Consider Figure 2, and imagine that the user has typed some stuff in the first and last name fields. Then the user clicks away from the workspace (viewmodel) entirely, either by clicking a different customer tab, or possibly a completely different viewmodel in the same application. In this case, what I'd like to have happen is for the application to ask "Hey, did you want to save your changes? Yes/No/Cancel" and respond appropriately. This has presented... challenges.
Because I'd like the user to be able to 'cancel' that first-pass suggests needing PreviewLostKeyboardFocus (since I could set Handled=true and cancel the focus shift). However, several user actions (such as clicking the tab of a different workspace) don't shift keyboard focus. LostFocus covers me better in that respect, but that's only after the focus has already been lost (though of course I could switch it back?) and there are issues with determining if the event was from the view itself (i.e., we're leaving the whole view) or if it's simply bubbled up from some contained object.
And big picture on all this - this seems to be an issue for the view, but then that implies writing code in the view rather than the magic viewmodel. Which makes me think i'm not looking at this correctly.
So I'm hoping I'm missing some big conceptual a-ha that will make all this clear. Help?
You need to concentrate on your model rather than your view. That is, what does change that should trigger your logic? In this case, I'd say it's when an attempt is made to change the active tab.
So you need an overarching view model whose responsibilities are:
Expose a collection of all sub view models (each of which appears in its own tab)
Track the active (selected) sub view model (ie. the active tab)
Your view would bind to these properties in the usual way:
<TabControl ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}"/>
The SelectedTab property would apply your logic as follows:
Is the current tab dirty?
If so, prompt the user via a service
If the user cancels, don't change the active tab
If the user saves or discards changes, then change the active tab
I think the key thing you're missing is the overarching view model. Working your way through my ActiveAwareCommand sample project may help increase your understanding.