I have an application which I use to select some stuffs from Git Repository.
This is the Basic Design of the application.
The whole window has a ViewModel, inside which i have defined two instances of view models A & B represending two user controls. The View Model B, is a status bar and only have a string in it which shows a text which can be anything. The View Model A, is another user control, where i can search for User Stories. So basically i want to show the totals from View Model A in View Model B in the UI. I tried injecting VM B into A, but that doesnt reflect in the window.How can i resolve this using WPF MVVM pattern?
This is the actual design of the application.
4
It’s hard to understand what you’re trying to achieve with your given explanation. However, from what I understand, you have a ContentControl or another UIElement with a Content attribute. You could instead add another ContentControl and split your window into two, so you have two ContentControls for the window.
<Window.DataContext>
<StaticResource ResourceKey="ViewModelCollection" />
</Window.DataContext>
...
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="500" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<ContentControl
Grid.Column="0"
Grid.Row="0"
Content="{Binding MainView.CurrentView}">
</ContentControl>
<ContentControl
Grid.Column="0"
Grid.Row="1"
Content="{Binding StatusBar.CurrentView}">
</ContentControl>
</Grid>
To show two different CurrentViews at once, you’ll need to add another class to your project. For example, you can create a StatusBarViewModel class with a RelayCommand to set the CurrentView of your status bar to the appropriate UserControl.
Furthermore, you can create a ViewModelCollection class that holds the MainViewModel and StatusBarViewModel as properties:
class ViewModelCollection
{
public ViewModelCollection()
{
MainView = new MainViewModel();
StatusBar = new StatusBarViewModel();
}
private MainViewModel _MainView;
private StatusBarViewModel _StatusBar;
public MainViewModel MainView
{
get { return _MainView; }
set { _MainView = value; }
}
public StatusBarViewModel StatusBar
{
get { return _StatusBar; }
set { _StatusBar = value; }
}
}
Don’t forget to reference your ViewModelCollection in your App.xaml and set it as the DataContext for your window:
<viewModel:ViewModelCollection x:Key="ViewModelCollection"/>
This approach ensures that you can manage multiple views and view models effectively within your window, with each content area bound to its respective view model.
I assume you want “VM B” to know about the changes that are happening in “VM A”. You have couple of options to accomplish this without much effort, I will elaborate on the simplest one:
-
Use a common state class (a manager class), which contains event that informs about changes
Example:public class AppManager { public event EventHandler<string> AppNameChanged; public void ChangeAppName(string newName) { AppNameChanged?.Invoke(this, newName); } } public class ViewModelA { readonly AppManager _appManager; public List<string> AppNamesList { get; set; } private string _selectedName; public string SelectedName { get =>_selectedName; set { _selectedName = value; _appManager.ChangeAppName(value); } } public ViewModelA(AppManager appManager) { AppNamesList = new List<string>(); } } public class ViewModelB { readonly AppManager _appManager; public ViewModelB(AppManager appManager) { _appManager = appManager; _appManager.AppNameChanged += (sender, newName) => { Console.WriteLine($"New App Name : {newName}"); }; } }
-
Use Messeging systems (for example from Community MVVM toolkit) to send notification. Example:
public record AppNameMessage(string Name); public class Message : ValueChangedMessage<AppNameMessage> { public Message(string Name) : base(new AppNameMessage(Name)) { } } public class ViewModelA { public List<string> AppNamesList { get; set; } private string _selectedName; public string SelectedName { get => _selectedName; set { _selectedName = value; WeakReferenceMessenger.Default.Send<AppNameMessage>(new( new (value))); } } } public class ViewModelB { public ViewModelB() { WeakReferenceMessenger.Default.Register<AppNameMessage>(this, (sender, message) => { Console.WriteLine($"New App Name : {message.Name}"); }); } }
Hope that help you out