I am writing an app for windows 8 and I have a UI class called GroupedItemsPage which inherits from LayoutAwarePage that contains the data :
this.DefaultViewModel["Groups"] = sampleDataGroups;
Each item in sampleDataGroups is binded to a tile in the UI and sampleDataGroups is a class which inherits from BindableBase and each property is set using
set{this.SetProperty(ref this._property, value); }
What I would like to do is to be able to catch a general event in my UI class GroupedItemsPage each time a property in sampleDataGroups is changed (so that I can rewrite sampleDataGroups to a file). I've done some research and I've only really found how to do get the notify event caught for sampleDataGroups, but not if I want sampleDataGroups to notify GroupedItemsPage?
Your page should not be writing data to a file. It's more of a duty of the view model or model rather. If you really have to though then you will need to subscribe to the PropertyChanged event declared by the type of your sampleDataGroups variable and handle the event in your page object.
Related
all!
In my main window I have a Grid with 2 columns. In column 0 is a usercontrol with settings, in column 1 is usercontrol with content.
The goal is to reset usercontrol with content when settings are changed. What is the right "MVVM"-way to do it?
Both usercontrols are implemented in MVVM-way, having all business logic in ViewModels.
Say I have a CheckBox bound to a Property in the settings-usercontrol:
Settings.xaml
...
<CheckBox IsChecked="{Binding Path=MySettingNr1}">
...
In Settings_ViewModel.cs
...
public bool MySettingNr1
{
get
{
return _model.SttNr1;
}
set
{
if(_model.SttNr1 == value) return;
_model.SttNr1 = value;
OnPropertyChanged(nameof(MySettingNr1));
}
}
...
How can I notify my content usercontrol if user clicks this checkbox?
Routed event would possibly not do, because both usercontrols are neighbours in the main window grid.
The only way I thought about was to fire an event in the usercontrol with settings, catch it in main windows and call a function of the usercontrol with content. Is there a way to make this call chain shorter?
Thanks in advance.
You could use a single shared view model for the window that both user controls bind to, i.e. they both inherit the DataContext of the parent window. This way they could communicate through the shared view model directly.
If you prefer to have two different view models, one for each user control, you could use an event aggregator or a messenger to send an event/message from one view model to antoher in a loosely coupled way.
Most MVVM libraries have implemented solutions for this. Prism uses an event aggregator and MvvmLight uses a messenger, for example.
Please refer to this blog post for more information about the concept.
I'm working on a project with WPF/Prism. The application has different modules and one of those modules can change the culture of the resx object. This works fine and each module loaded will display the translated text.
In case any module has already been loaded, the text will not be updated. First, I tried an approach with x:Static but quickly realized that a static value doesn't help my issue. Now I've implemented a get-only property in my view model that returns the localized string.
public string UserDetailsLabel => Messages.UserDetailsLabel;
<TextBlock Text="{Binding UserDetailsLabel, Mode=OneWay, NotifyOnSourceUpdated=True}"/>
However, I have no idea where to tell WPF (or Prism) that the culture has changed and to update the displayed value. The module that changes the culture sets the Culture property on Messages (generated in Messages.Designer.cs).
Is there a way to notify that the value changed?
Is there a way to notify that the value changed?
Implement INotifyPropertyChanged and raise the PropertyChanged event for the data-bound UserDetailsLabel property.
This is the way to notify WPF that the source value has changed.
In the context of a multi-module Prism application, you could for example use the event aggregator to raise an event that each view model handles by raising the PropertyChanged event for all data-bound properties that need to be refreshed in the view.
I solved my problem by attaching the Loaded event in the UserControl xaml definition. The view then asks my view model to update the UI.
The view model then calls RaisePropertyChanged(nameof(UserDetailsLabel)) and updates the view.
// UserListView.xaml
<UserControl ... Loaded="UserListView_OnLoaded">...</UserControl>
// UserListView.xaml.cs
private void UserListView_OnLoaded(object sender, RoutedEventArgs e) {
var dataContext = (IUserListViewModel) DataContext;
dataContext.RefreshUI();
}
// UserListViewModel.cs
public void RefreshUI() {
RaisePropertyChanged(nameof(IUserListViewModel));
}
I use an observable collection with a selecteditem (name + detail) to push a new contentpage in my navigation and in this new page i modify the name of this selected item but in an other list.
I would like to refresh the data in the observable collection with this other list (saved in an internal storage)
So, can i use an event to notify the previous viewmodel than i push the back button and if it possible which event can i use?
Xamarin.Forms.Page
//
// Summary:
// When overridden, allows application developers to customize behavior immediately
// prior to the Xamarin.Forms.Page becoming visible.
//
// Remarks:
// To be added.
protected virtual void OnAppearing();
This may be helpfull you'll need to override it in your page code.
Overriding the OnAppearing method seems the simplest way to achieve this. This way you'll keep the logic to refresh the data in the page that belongs with the viewmodel that needs to be refreshed. When the page re-appears, it can trigger some logic in the ViewModel to refresh the ObservableCollection.
Another option is to use the MessagingCenter that comes with Xamarin.Forms: https://developer.xamarin.com/guides/xamarin-forms/messaging-center/ This allows pub/sub style messaging between components while staying loosely coupled. You could have the class that manages the internal storage publish messages whenever the list in the gets updated and broadcast this to ViewModels that have subscribed to these updates.
In this particular case, overriding OnAppearing seems the simplest solution though.
I am trying to program in MVVM and I have the following use case:
A TextBox's text is bound to a property in the VM
A Button is command bound to a relay command
When the user presses the Button, the web browser's Navigate(url) method is called with the URL being the text in the TextBox
Above is the use case I want to create, but 1 and 2 is possible using the MVVM design pattern, but I could not find an adequate way to invoke the browser's Navigate() method. First of all, is it possible to call a method of a control from VM (please let me know if there is a way)? And in the above use case, what would be the appropriate way to structure the program if it is not possible?
Thanks
You could do the following:
Add a property MyUrl to your ViewModel
Bind MyUrl to your WebBrower's Source property
Make sure the property implements INotifyPropertyChanged. Then your Xaml:
<WebBrowser Source="{Binding MyUrl}" />
What if you REALLY wanted to call a UI method from the ViewModel?
If you ever do run into a situation where you absolutely need to call a method on a UI control for instance, you can hook up events on the ViewModel and then your UI registers to this event and does something UI specific...
VM code...
//... some VM logic
EpicNavigateEvent(url) // raise event, allowing UI to handle how
In your code-behind on your view (this is the part where some MVVM purests freak), you could register the event:
myVm.Navigate += doSomeNavigation;
...
public void doSomeNavigation(string url)
{
// call Navigate
}
I've successfully used this approach for applications where we have a single ViewModel layer and multiple technologies hooked up the views (WinForms, WPF and Asp.Net).
If you're looking for something more elegant, have a look at the User Interaction Patterns on MSDN.
The concept is the same though: Call something on the VM and the View is handles it appropriately.
Common scenarios for this type of approach is want to show a message to the user from the VM. Your VM should raise an event saying: ShowMyMessage("You're awesome"), then your UI is notified and handles it: MessageBox.Show(msg) or whatever.
As long as you stick to there rules you should be golden:
ViewModels should NOT be concerned about UI code
Views must ONLY handle the presentation of the data provided by your ViewModels.
Don't overcomplicate it. KISS...
I have the following property in my view model and the view is binding to this property.
All works fine except for a special case where the ActiveCategory (within the _catManager) can change from other events (outside of this view).
I don't want to expose the entire Category Manager in the view model so I'm only exposing what properties I need. What is the best way to do this so that the view gets notified of all changes, even those changes not triggered within this view model?
public ICategory SelectedCategory
{
get
{
return _catManager.ActiveCategory;
}
set
{
_catManager.ActiveCategory = value;
OnPropertyChanged("SelectedCategory");
}
}
Have your viewmodel hook into the _catManager's INotifyPropertyChanged event and have it relay the property change events through the viewmodel. When you see "ActiveCategory" come through, that means you need to raise an INPC for "SelectedCategory".
You need to delegate notification to whatever class _catManager is as well.
So a change to it's ActiveCategory property raises a notification.
One way would be to add a handler in the the class that has it as a property and then raise a notification that it's _catManager has changed somehow.