in my view, i have two chart controls of type MyChart:
MyChart1
MyChart2
The chart user control has a button called Refresh. Clicking on the button refreshes their item source and they display new data.
In the ViewModel of the view, I have two properties of type MyChart, one for each MyChart.
When I click on the Refresh button, how do I raise RaisePropertyChanged event of the view model of the view?
This is not a correct implementation of MVVM, as you have application logic coded into the View layer.
The standard approach would be to have a Command property on your ViewModel, then bind Button.Command to the ViewModel.Command. This will allow you to handle the refreshing in the ViewModel and give you a place to write any additional code you need to write.
To answer your question, if you are using MVVM, the properties displayed in the View actually exist in the ViewModel, so you should be able to handle PropertyChanged easily enough in the ViewModel using this.PropertyChanged += new PropertyChangedEventHandler(ViewModel_PropertyChanged);
Related
In my application I have dialogs with mutiple tabs. Im using Prism to register the views with the TabControl.
What I want is a validation for the entire dialog to diable/enable the save button.
The Problem: Currently we have a view-triggered validation. Means every bound item implements the IDataErrorInfo interface. When the View is displayed the binding triggers the interface and displays and error on the UI. The Control has the HasError Property set to true, save button gets disabled.
But the validation does not get tiggered until the view is displayed. Should I move the validation to the ViewModel and validate the Properties on my own or is there a solution to validate inactive views in a TabControl?
There isn't quite enough information to go off of I your question, so I can only guess. First off, you must understand that there are no inactive views in a TabControl. There is only one view in the TabControls visual tree at one time, and that is the selected tab. This means the other views are removed from the visual tree until they are selected. This really doesn't matter though, as validation is controlled via the ViewModel. You ViewModel most likely has a Command bound to your Save button. This command should have a CanExecute defined returning IDataErrorInfo.Error != null (meaning you have no errors). This is where you will check the validity of your objects. Return false if you have any errors, and true if you don't. Hook into the property changed event of your objects, and call the SaveCommand.RaiseCanExecuteChange method to recheck the state of your button.
If each view a tab has it's own ViewModel, hence it's own Save command, I would recommend using a CompositeCommand. This is really an unknown since I don't know how you have architected your dialogs, views, or ViewModels.
How is this possible for WinRT?
I have read the answer for WPF How to programmatically click a button in WPF?, but does not really help me.
Anyone solved such an issue?
First, I'd like to say if you want the button to "appear to have been pressed (in terms of animation/highlight effects) this won't help you but otherwise it should.
My Advice to you would be to follow the Model-View-ViewModel (MVVM) design pattern when designing your application if you haven't already. That way instead of calling the "button" click you can simply execute the method in your viewmodel that would normally be bound to that click.
Example:
You create a model class representing data in your database.
You create a view (page/window) with buttons and other UI elements on it.
You create a ViewModel class that has a series of public methods and collections.
Now in the XAML for the View, you bind the ViewModel as your DataContext and bind the public properties of the ViewModel to your collections (ItemSource for a ListBox being bound to an ObservableCollection is on example). You can create public methods that are "commands" and bind them your buttons so that when the button click event is fired, the command in the view model is executed. Now for all your unit tests and for any other reason you might want to programmatically "click" the button, you can simply call the associated methods in the ViewModel and never worry about what the actual View is doing.
In my CustomerCollectionViewModel, I have a ObservableCollection<CustomerViewModel> CustomerList and a property called CurrentCount property that returns CustomerList.Count().
In the associate view, the I bind CustomerList to a DataGrid and CurrentCount to a label. In reality their are many other dependent properties that present aggregate information about the the CustomerList. About a dozen or so.
My current understanding of MVVM would require bloating the CustomerViewModel with SendPropertyChanged() for all the aggregate summery labels in UI. Isn't it possible to all CustomerViewModel update events that bubble out of the DataGrid be caught and then fan out to update the aggregate labels.
I bound the lost focus event of a textbox style to a command in the immediate viewmodel's data context. This command takes the textbox name as the parameter. This was achieved through using MVVM-Light's relay command, but there are other ways of doing this.
Then in my viewmodel I have a LostFocusCommand that I use to "refresh" my aggregate values and notify the UI of the changes.
All I have to to is apply the text box style to the textboxes i want to trigger this command event (i have a style for comboboxes etc. that binds to the same command, so It does not just have to be text boxes.).
One place to maintain code and you can evaluate the textbox name to take more specific or isolated actions.
Hope this helps. can't be more specific without seeing code or knowing what framework your using.
I am in the process of re-writing one of our large Silverlight apps to use PRISM and the MVVM design pattern.
A very common scenario is a DataGrid in the View. Double clicking a row allows the user to edit the entity represented by the row, using a ChildWindow.
I am tempted just to capture the DoubleClick event in the code behind, create a new ChildWindow of the proper type, and set the DataContext to be DataGrid.SelectedItem.
I know that this is not the proper way to handle this scenario with PRISM and MVVM, however.
I would love advice on what is! (re: my title...it seems like InteractionRequest might be the best way to do this?)
Thanks...
EDIT: We did end up deciding to go with InteractionRequest for our solution. We almost always use "Notification" as the type and pass a new ViewModel (each ChildWindow has its own) as the Content.
In our case the ChildWindow view was complex enough to warrant its own viewmodel. This view isn't too closely coupled with the data grid view.
So, we have an EventTrigger attached to the data grid (we actually use Telerik's data grid) in XAML. The event trigger executes a command in the view model using InvokeCommandAction.
The command publishes an aggregated event that has the selected item as the payload. The event is picked up by the central application controller that is responsible for creating the ChildWindow view and a corresponding view model (using the event payload as the context).
I think that interaction request could potentially be used in your case, but based on my understanding the idea behind an interaction request is a very simple Ok or Yes/No interaction. You might be pushing the boundaries with a bunch of text boxes, validation, etc.
Hi, Please consider the custom wp7 message box above. I am looking to see what is the cleanest way to bind a views textbox to a property on the view model only after a button is clicked. The only way I can work out is to have two properties and use a command on the button to assign the value of the first prop to the main prop. The main prop should only receive the value from the textbox only if the user clicks the tick button and not if they cancel (by pressing the back button).
I am using MVVM Light.
What about catching the click event and sending the changed text from View to ViewModel via Messenger. On ViewModel the property would be only a getter.
I think that the way you do it is ok.
Have a temporary binded property and main property synced with the temporary one only when messagebox is accepted.