The trick with MVVM is the
View
is a visual representation of the data. The
ViewModel
is the interface between the data and the view.
So for the
Tabs
to reflect the
Button
clicks, you should be binding the
Tabs
to the data and the
Button
clicks are bound to the
Command
that passes a
CommandParameter
to the
ViewModel
. Then the
ViewModel
updates the data and the binding will notify the
View
of the changes, then the
View
will refresh the UI.
I'm not quite sure which framework you are using or how you're wiring up your binding, but here is a minimal solution to do what you are asking.
So first we need to set up the
Command
to enable the
Button
in the
View
to pass data to the
ViewModel
:
public abstract class CommandBase : ICommand
{
public event EventHandler? CanExecuteChanged;
public virtual bool CanExecute(object? parameter) => true;
public abstract void Execute(object? parameter);
protected void OnCanExecuteChanged()
=> CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
public class ButtonClickCommand : CommandBase
{
public ButtonClickCommand(Action<string> callback)
=> _callback = callback;
private readonly Action<string>? _callback;
public override void Execute(object? parameter)
=> _callback?.Invoke(parameter as string ?? string.Empty);
}
Next we need to set up the
ViewModel
to:
1. Expose an
ObservableCollection
for the
Tabs
2. Expose and wire up then the
Command
for the
Buttons
3. A method to update the
Tabs
collection with the new
Tabs
as the
Button
s are clicked
public class MainViewModel
{
public MainViewModel()
=> ButtonClickCommand = new ButtonClickCommand(OnClicked);
public ICommand? ButtonClickCommand { get; }
public ObservableCollection<string> Tabs { get; } = new();
private void OnClicked(string buttonName)
=> Tabs.Add(buttonName);
}
Now we set the
DataConext
with the
ViewModel
for the
View
:
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new MainViewModel();
InitializeComponent();
}
}
Lastly, we can now wire up the view:
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Padding" Value="20 10" />
<Setter Property="Margin" Value="5 10"/>
</Style>
</StackPanel.Resources>
<Button Content="Button 1"
Command="{Binding ButtonClickCommand}"
CommandParameter="Button 1" />
<Button Content="Button 2"
Command="{Binding ButtonClickCommand}"
CommandParameter="Button 2" />
<Button Content="Button 3"
Command="{Binding ButtonClickCommand}"
CommandParameter="Button 3" />
</StackPanel>
<TabControl Grid.Row="1" Height="100"
ItemsSource="{Binding Tabs}">
</TabControl>
When you run the code, each
Button
click will notify the
ViewModel
via the
Command
and a new
Tab
will be added to the
Tabs
collection. The
Tabs
colllection will notify the
View
via the binding and the
Tabs
control will add the new
Tab
.
This is the bare minimum to getting it working. The rest is up to you.
Hope this answers your question.