HI,
with MVVM pattern you are very flexible. In small applications you can use one ViewModel for MainWindow with UserControls like in following demo. In large applications you can use main ViewModel and ViewModels for UserControls or second Windows.
XAML MainWindow:
<Window x:Class="WpfApp1.Window029"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp029"
xmlns:vHyprLnk="clr-namespace:WpfApp029"
xmlns:uc1="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:ViewModel x:Key="vm"/>
</Window.Resources>
<StackPanel DataContext="{StaticResource vm}">
<Button Content="Button in MainWindow" Command="{Binding Cmd}" CommandParameter="From MainWindow"/>
<uc1:Window029UC1 Margin="5"/>
<Label Content="{Binding Status}"/>
<ListBox HorizontalAlignment="Stretch" Height="200" VerticalAlignment="Top"
ItemsSource="{Binding View}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="22" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding AppName, Mode=OneWay}"/>
<vHyprLnk:vHyperlinkButton Grid.Row="0" Grid.Column="1" Content="Tbl"
Command="{Binding BtnTable_Click, Source={StaticResource vm}}" CommandParameter="{Binding}" />
<vHyprLnk:vHyperlinkButton Grid.Row="0" Grid.Column="2" Content="SP"
Command="{Binding BtnStoredProcedure_Click, Source={StaticResource vm}}" CommandParameter="{Binding}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
Classes:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
namespace WpfApp029
{
public class ViewModel : INotifyPropertyChanged
{
private string _status;
public string Status { get => this._status; set { this._status = value; OnPropertyChanged(); } }
private CollectionViewSource cvs = new CollectionViewSource();
public ICollectionView View { get => cvs.View; }
public ICommand BtnTable_Click
{
get => new RelayCommand((state) => Status = $"BtnTable_Click: {((WcRecentView_lst_Binding)state).AppName}");
}
public ICommand BtnStoredProcedure_Click
{
get => new RelayCommand((state) => Status = $"BtnStoredProcedure_Click: {((WcRecentView_lst_Binding)state).AppName}");
}
public ICommand Cmd { get => new RelayCommand(CmdExec); }
private void CmdExec(object state)
{
switch (state.ToString())
{
case "From MainWindow":
Status = "Click from MainWindow";
break;
case "From UserControl":
Status = "Click from UserControl";
break;
case "Load From UserControl":
LoadData();
break;
default:
break;
}
}
private void LoadData()
{
List<WcRecentView_lst_Binding> list = new List<WcRecentView_lst_Binding>();
for (int i = 0; i < 100; i++) list.Add(new WcRecentView_lst_Binding() { AppName = $"App {i}" });
cvs.Source = list;
OnPropertyChanged(nameof(View));
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
public class WcRecentView_lst_Binding
{
public string AppName { get; set; }
}
public class vHyperlinkButton : Button { }
public class RelayCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _action;
public RelayCommand(Action<object> action) { _action = action; _canExecute = null; }
public RelayCommand(Action<object> action, Predicate<object> canExecute) { _action = action; _canExecute = canExecute; }
public void Execute(object o) => _action(o);
public bool CanExecute(object o) => _canExecute == null ? true : _canExecute(o);
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
And XAML UserControl:
<UserControl x:Class="WpfControlLibrary1.Window029UC1"
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:WpfControlLibrary1"
mc:Ignorable="d"
d:DesignHeight="80" d:DesignWidth="200">
<UserControl.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="5"/>
</Style>
</UserControl.Resources>
<Border BorderBrush="Red" BorderThickness="3">
<StackPanel>
<Button Content="Button in UserControl" Command="{Binding Cmd}" CommandParameter="From UserControl"/>
<Button Content="Start Load from UserControl" Command="{Binding Cmd}" CommandParameter="Load From UserControl"/>
</StackPanel>
</Border>
</UserControl>
Result: