Fire an event when a property dependency in another user control changes - wpf

I have a custom treeview inside a user control. It exposes a dependency property that represents the currently selected treeviewitem. In the same window i have another user control that should change content of it's controls when the selected item changes. I need to do this changes from code behind. How do i fire up an event in the second user control when the selected item changes in the first one?

As the Dependency property whose change you want to be notified about is one created by yourself, why don't you register a PropertyChangedCallback for that property in your user control? This way, you can add a SelectedItemChanged event to the control and raise it from the PropertyChangedCallback code.
Any object that needs to know when the selectedItem has changed just has to listen to this new event.

Related

Update Dependency Property prior to program exit

I have created a dependency property of type Binary on a RichTextBox which allows me to bind to a FlowDocument which is in binary form (byte[]) within the ViewModel. This works well, the property converts to and back correctly.
Whenever the RichTextBox looses focus then the value of the dependency property is updated with the new binary representation of the FlowDocument.
My problem is that if I have been using the RichTextBox and I close the window, the RichTextBox does not lose focus and hence the dependency property is not updated with the new binary representation of the FlowDocument and therefore new changes are not commited to the database. In my ViewModel I have a method CleanUp which gets called when a ViewModel is getting ready to be disposed, where I can save the updated document.
How can I get the dependency property to update itself as the RichTextBox doesn't lose focus if the user clicks to close the window?
I brainstormed the following:
Tell the dependency property to update itself via a message broadcast. I am not clear on how to register a message listener within the dependency property.
Query the RichTextBox directly, get the Document, convert it to a binary object manually.
Get the view to move focus to a dummy control, so that the dependency property now updates itself.
What do you guys think?
Update: the on changed event for the dependency property adds a event handler which is waiting for the RichTextBox to loose focus. It is this handler that updates the dependency with its new value.
Use an UpdateSourceTrigger of "PropertyChanged"
Something like:
{Binding Path=MyProperty,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}
I had a similar problem once, the solution I used was to move the focus to a different control and I never had any problems with this.
In my case there were several editable controls in the window so I didn't have to use a dummy control.
What's stopping you from handling the closing/closed event of the Window and moving focus or updating the binding?

How can I set the keyboard focus to the content of a ContentPresenter when it changes?

I have a ContentControl in my view which is databound to the CurrentItem property of my viewmodel. The objects that are exposed via CurrentItem each has its own DataTemplate.
When the CurrentItem property changes, the appropriate DataTemplate for that item is displayed, as it should be. However, I cannot find out a way to set the keyboard focus to the content of the DataTemplate.
Even if I manually set the keyboard focus to the DataTemplate, if the CurrentItem property changes (and a new Template is instantiated) the focus is lost (FocusManager.GetFocussedElement returns null).
How can I set the keyboard focus to the content of the ContentPresenter when it changes?
I believe you can use the LayoutUpdated event on either your ContentControl or the ContentPresenter. This should fire anytime the Content/ContentTemplate/etc changes.
Alternatively, you could derive a class from ContentControl then override the OnContentChanged, OnContentTemplateChanged, etc methods. Then you'd need to search down the visual tree and set the focus. You may need to use the Dispatcher to delay the focus setting code.

WPF MVVM UpdateSourceTrigger=Excplict

i've a contentcontrol in my Wpf-App (MVVM) which is bound to an object and displays the objects properties in textboxes, so the user can edit the values of the properties.
I want to implement undo/redo functionality with the command pattern of the GoF.
For this i need a point where i can create the command and set it into my undomanager.
My idea was to add a submitbutton. When the button is pressed, i update the sources of the textboxes (my properties) and create my command object to make the changes undoable (saving the old state of the object and the new state).
But:
- For using a submit button i need to set UpdateSourceTrigger of the textboxes to Explicit. If i want to update my sources i need to reference the controls in my view, which is bad as far as i've learned. How can i do that?
With MVVM i have to create a Command (WPF Command, not my undo redo command) for the SubmitButton but i don't see how to apply the changes to the properties from that command without referencing the textboxes (further hey are generated via datatemplates).
Thanks Walter
I assume your TextBox controls are bound to the properties in the ViewModel class. If you bind your submit button to a ViewModel Command which in turn can add appropriate command to you Command Pattern Collection and also changes some of ViewModel properties, the values in the Textbox controls will also be updated. Now, for a Textbox to update it's value when the value of a property it is bound to changes, the ViewModel class needs to implement INotifyPropertyChanged interface and raise the PropertyChanged event from the property setter with that's property's name as an argument.

ListView.SelectionChanged to RoutedCommand

I'm working in the MVVM design pattern with WPF. I have a ContextMenu with several items in it on a ListView. Based on the number of items selected in the ListView, I want to enable/disable certain MenuItems. Is there a way to route the SelectionChanged event along with the number of selected items in the ListView directly to the view model. If so, I can define a dependency property in the VM for IsEnabled quite easily. I'm just trying to avoid code-behind to handle this.
Kelly
You can use an attached behavior to route the SelectionChanged event to your VM. Basically, you create an attached property of type bool. When this property is set to true, you register an event handler for the SelectionChanged event of the target Menu.
Then an attached property can contains the command to execute (databound to a RelayCommand-like command in your VM).
Check those posts for more details:
http://www.japf.fr/2008/12/how-to-attach-commands-to-any-uielement/
http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/

How do I BringToView the latest item added to a bound ObservableCollection

I have a silverlight control (View) which displays a list of items in a specified property of the datacontext (viewmodel).
What I need is for the scrollviewer in my control to scroll to the top or bottom depending on where the latest item has been added to the list. (It'll always be either the beginning or the end of the list, I don't need to worry about middle of list insertions.)
In WPF i'd just use the DataContextChanged event to start listening to the viewmodel, but in silverlight that event is internal.
Any ideas on how to tackle this?
A good starting point is Attached Behaviors on CodeProject.
A useful behavior would watch the ListBox.ItemsSource and attach to the observable collection when set. On the collection changed event, use ListBox.ScrollIntoView to display the changed item.
I can't use the CollectionChangedEvent of ObservableCollection since I need the DataContextChanged event to get the DataContext which holds the Collection in the first place.
Would you not do this in the ViewModel?
Whatever ViewModel has the ObservableCollection, expose a property of type T named SelectedItem and whenever the ObservableCollection changes with a new item, the CollectionChanged event will allow you to set the SelectedItem property. Once this is done, wire up the SelectedItem in the control to this property on your ViewModel.
This will obviously only work with controls like ListBox where a SelectedItem property exists.
In place of DataContextChanged in WPF , you can use CollectionChanged event of ObservableCollection. In the collection changed you will get to know the NewItem Index.

Resources