Reputation: 235
I want to be able to share controls between my main window and tab controls. Right now, I have a tab control and status bar on the main window. Status bar contains a button and progress bar. I want to share the progress bar. When the button is clicked, it resets progress bar.
The tabs contain a button. When clicked, it should increase the progress bar by 1.
What I've done: after digging through SO/other all day, I was able to set this up.
I need advice on how to talk to MainWindowViewModel in TabControl1View.
<Window x:Class="TabControlTest.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TabControlTest"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<DockPanel>
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem HorizontalContentAlignment="Stretch" DockPanel.Dock="Top">
<Button Height="25" Content="Reset" Command="{Binding MainWindowViewModel_ButtonClickCommand}"/>
</StatusBarItem>
<StatusBarItem HorizontalContentAlignment="Stretch" DockPanel.Dock="Bottom">
<ProgressBar Height="25" Maximum="10" Value="{Binding MainWindowViewModel_Progress, Mode=TwoWay}"/>
</StatusBarItem>
</StatusBar>
<TabControl>
<TabItem>
<local:TabControl1View/>
</TabItem>
</TabControl>
</DockPanel>
class MainWindowViewModel : ViewModelBase
{
int progress = 0;
public int MainWindowViewModel_Progress
{
get
{
return progress;
}
set
{
SetAndNotify(ref this.progress, value, () => this.MainWindowViewModel_Progress);
}
}
ICommand _ButtonClickCommand;
public ICommand MainWindowViewModel_ButtonClickCommand
{
get
{
return _ButtonClickCommand ?? (_ButtonClickCommand = new CommandHandler(() => MainWindowViewModel_ButtonClick(), true));
}
}
public void MainWindowViewModel_ButtonClick()
{
MainWindowViewModel_Progress = 0; // Reset progress
}
}
x
<UserControl x:Class="TabControlTest.TabControl1View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TabControlTest"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<local:TabControl1ViewModel/>
</UserControl.DataContext>
<Grid>
<Button Content="UP" Command="{Binding TabControl1ViewModel_UpClickCommand}"/>
</Grid>
class TabControl1ViewModel : ViewModelBase
{
ICommand _UpClickCommand;
public ICommand TabControl1ViewModel_UpClickCommand
{
get
{
return _UpClickCommand ?? (_UpClickCommand = new CommandHandler(() => TabControl1ViewModel_UpClick(), true));
}
}
public void TabControl1ViewModel_UpClick()
{
// I want to increase the progress bar here
}
}
I found a good answer on using a mediator pattern here: How can I update a property of mainWindowViewModel from another ViewModel?
But I don't understand how I can store a reference to TabControl1ViewModel in MainWindowViewModel.
Also found a ton of articles saying to declare the ViewModels inside MainViewModel and keep track of them, but they were always code snippets.
Question: how do I pass MainViewModel.Progress to TabControlViewModel?
I'm now going down the path of trying to put something like this in my MainViewModel
MainViewModel.ProgressChanged = TabControlView.(get TabControlViewModel).ProgressChanged
Upvotes: 0
Views: 96
Reputation: 7903
When you do this
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
or
<UserControl.DataContext>
<local:TabControl1ViewModel/>
</UserControl.DataContext>
You are letting the View to create a instance of MainWindowViewModel
or TabControl1ViewModel
by itself and bind it to your View's datacontext. That makes you loose control of passing any constructor parameter to the control.
In your MainWindowViewModel
's constructor initialize the User control's Datacontext like
class MainWindowViewModel
{
MainWindowViewModel
{
ChildViewModel = new TabControl1ViewModel(this);
}
public TabControl1ViewModel ChildViewModel {get; private set;}
}
class TabControl1ViewModel
{
public MainWindowViewModel ParentViewModel {get; private set;}
TabControl1ViewModel(MainWindowViewModel mainWindowViewModel)
{
ParentViewModel = mainWindowViewModel;
}
}
View.Xaml
<Window x:Class="TabControlTest.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TabControlTest"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<DockPanel>
.
.
.
<TabControl>
<TabItem>
<local:TabControl1View DataContext={Binding ChildViewModel}/>
</TabItem>
</TabControl>
</DockPanel>
Upvotes: 1