I'm creating a WPF Molds app that contains 2 windows: MainWindow with DataGrid, and AddEditWindow which allows to Add/Edit Molds.
I have a EditButton which located in a TemplateColumn of DataGrid:
<DataGridTemplateColumn Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Width="150"
Height="40"
BorderThickness="2"
BorderBrush="DarkRed"
Background="Red"
Foreground="White"
Content="Edit"
Name="BtnEdit"
CommandParameter="{Binding}"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.AddEditWindowCommand}">
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
AddEditWindowCommand:
public ICommand AddEditWindowCommand { get; }
private bool CanAddEditWindowCommandExecute(object SelectedRow) => true;
private void OnAddEditWindowCommandExecuted(object SelectedRow)
{
AddEditWindow window = new AddEditWindow();
window.Show();
}
And I want to pass DataContext to the AddEditWindowViewModel. In a Code-Behind, I could done something like this:
private void BtnEdit_Click(object sender, RoutedEventArgs e)
{
AddEditWindow addEditWindow = new AddEditWindow((sender as Button).DataContext as Molds);
addEditWindow.Show();
}
And then retrieve it AddEditWindow like this:
private Molds _currentMold = new Molds();
public GamesEdit(Molds selectedMold)
{
InitializeComponent();
if (selectedMold != null)
{
_currentMold = selectedMold;
}
DataContext = _currentMold;
But in MVVM I can't. So, is there a way to do it without breaking MVVM pattern?
p.s. since I'm new to the MVVM, I would really appreciate detailed explanation.
update:
MainWindowViewModel:
internal class MainWindowViewModel : ViewModel
{
#region Variables
#region Textblocks for search
private Molds newMolds { get; set; } = new Molds();
public string TxtType
{
get => newMolds.Type;
set => newMolds.Type = value;
}
public string TxtName
{
get => newMolds.Name;
set => newMolds.Name = value;
}
public string TxtKus
{
get => newMolds.Kus;
set => newMolds.Kus = value;
}
#endregion
#region AllMolds
private ObservableCollection<Molds> allMolds = new ObservableCollection<Molds>(ApplicationContext.GetContext().Molds.ToList());
public ObservableCollection<Molds> AllMolds
{
get => allMolds;
set => allMolds = value;
}
#endregion
#region FilteredMolds
private ObservableCollection<Molds> filteredMolds = new ObservableCollection<Molds>(ApplicationContext.GetContext().Molds.ToList());
public ObservableCollection<Molds> FilteredMolds
{
get
{
filteredMolds = AllMolds;
var currentfilteredmolds = new List<Molds>(filteredMolds);
if (TxtName != null)
currentfilteredmolds = currentfilteredmolds.Where(p => p.Name.ToLower().Contains(TxtName.ToLower())).ToList();
if (TxtType != null)
currentfilteredmolds = currentfilteredmolds.Where(p => p.Type.ToLower().Contains(TxtType.ToLower())).ToList();
if (TxtKus != null)
currentfilteredmolds = currentfilteredmolds.Where(p => p.Kus.ToLower().Contains(TxtKus.ToLower())).ToList();
return new ObservableCollection<Molds>(currentfilteredmolds);
}
set => filteredMolds = value;
}
#endregion
#endregion
#region Commands
#region CloseApplicationCommand
public ICommand CloseApplicationCommand { get; }
private bool CanCloseApplicationCommandExecute(object p) => true;
private void OnCloseApplicationCommandExecuted(object p)
{
Application.Current.Shutdown();
}
#endregion
#region SearchCommand
public ICommand SearchCommand { get; }
private bool CanSearchCommandExecute(object p) => true;
private void OnSearchCommandExecuted(object p)
{
OnPropertyChanged("FilteredMolds");
}
#endregion
#region Open AddEditWindowCommand
public ICommand AddEditWindowCommand { get; }
private bool CanAddEditWindowCommandExecute(object SelectedRow) => true;
private void OnAddEditWindowCommandExecuted(object SelectedRow)
{
AddEditWindow window = new AddEditWindow();
window.Show();
}
#endregion
#region DeleteMoldCommand
public ICommand DeleteMoldCommand { get; }
private bool CanDeleteMoldCommandExecute(object SelectedItems)
{
if (SelectedItems != null) return true; else return false;
}
private void OnDeleteMoldCommandExecuted(object SelectedItems)
{
System.Collections.IList items = (System.Collections.IList)SelectedItems;
var moldsforRemoving = items?.Cast<Molds>().ToList();
if (MessageBox.Show($"You want to remove the following {moldsforRemoving.Count()} molds?", "Attention",
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
try
{
ApplicationContext.GetContext().Molds.RemoveRange(moldsforRemoving);
ApplicationContext.GetContext().SaveChanges();
MessageBox.Show("Data deleted successfully.", "Data deletion",
MessageBoxButton.OK, MessageBoxImage.Information);
AllMolds = new ObservableCollection<Molds>(ApplicationContext.GetContext().Molds.ToList());
OnPropertyChanged("FilteredMolds");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString(), "Error",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
#endregion
#region DragMoveCommand
public ICommand DragMoveCommand { get; }
private bool CanDragMoveCommandExecute(object p) => true;
private void OnDragMoveCommandExecuted(object p)
{
Application.Current.MainWindow.DragMove();
}
#endregion
#endregion
public MainWindowViewModel()
{
#region Command Samples
CloseApplicationCommand = new LamdaCommand(OnCloseApplicationCommandExecuted, CanCloseApplicationCommandExecute);
SearchCommand = new LamdaCommand(OnSearchCommandExecuted, CanSearchCommandExecute);
AddEditWindowCommand = new LamdaCommand(OnAddEditWindowCommandExecuted, CanAddEditWindowCommandExecute);
DeleteMoldCommand = new LamdaCommand(OnDeleteMoldCommandExecuted, CanDeleteMoldCommandExecute);
DragMoveCommand = new LamdaCommand(OnDragMoveCommandExecuted, CanDragMoveCommandExecute);
#endregion
#region Variable Samples for searching
TxtName = null;
TxtKus = null;
TxtType = null;
#endregion
}
}
AddEditWindowViewModel
internal class AddEditWindowViewModel : ViewModel
{
#region Variables
private Molds _currentMold = new Molds();
#endregion
#region Commands
#region CloseWindowCommand
public ICommand CloseWindowCommand { get; }
private bool CanCloseWindowCommandExecute(object p) => true;
private void OnCloseWindowCommandExecuted(object p)
{
Application.Current.Windows[1].Close();
}
#endregion
#region DragMoveAddEditWindowCommand
public ICommand DragMoveAddEditWindowCommand { get; }
private bool CanDragMoveAddEditWindowCommandExecute(object p) => true;
private void OnDragMoveAddEditWindowCommandExecuted(object p)
{
Application.Current.Windows[1].DragMove();
}
#endregion
#endregion
public AddEditWindowViewModel()
{
#region Command samples
CloseWindowCommand = new LamdaCommand(OnCloseWindowCommandExecuted, CanCloseWindowCommandExecute);
DragMoveAddEditWindowCommand = new LamdaCommand(OnDragMoveAddEditWindowCommandExecuted, CanDragMoveAddEditWindowCommandExecute);
#endregion
}
}
I connect them to the window using <Window.DataContext>:
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
Same goes for the AddEditWindowViewModel.
DataGrid binding:
<DataGrid x:Name="DGridMolds"
AutoGenerateColumns="False"
IsReadOnly="True"
Foreground="White"
BorderBrush="White"
Background="#2b2a38"
Grid.Column="1"
Grid.Row="1"
ItemsSource="{Binding Path=FilteredMolds}"
>
AddEditWindow.Xaml:
<Window.DataContext>
<vm:AddEditWindowViewModel/>
</Window.DataContext>
<Border Background="#2f2e3c"
CornerRadius="10">
<Border.InputBindings>
<MouseBinding Command="{Binding DragMoveAddEditWindowCommand}" MouseAction="LeftClick"/>
</Border.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1" Grid.Row="1" Orientation="Vertical">
<TextBlock Text="Add" FontSize="22" Foreground="White" HorizontalAlignment="Center" Margin="0,30,0,0"/>
<TextBox Foreground="White" Text="{Binding Type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5, 35, 5, 5" materialDesign:HintAssist.Hint="Type"/>
<TextBox Foreground="White" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5" materialDesign:HintAssist.Hint="Name"/>
<TextBox Foreground="White" Text="{Binding Kus, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5" materialDesign:HintAssist.Hint="Kus"/>