Not familiar with Stylet
or Caliburn
, once wanted to look at Prism
BUT some articles popped up, while searching about that, in my browser and read that I don't need anything else, for MVVM, other than INotifyPropertyChanged
in WPF which actually is true. At some point, to make life easier, you've to get into code behind otherwise it gets too complicated to handle simple matters.
If you want to populate a second window with various properties of the SelectedItem
of your DataGrid
of first window, you've to set the SelectedItem
as the DataContext
of your second window. Here's a small example, in the MainWindow.xaml
I've these:
<Grid Margin="20">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<DataGrid ItemsSource="{Binding Entries}"
SelectedItem="{Binding Selected}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Dr Head" Binding="{Binding DrHead}"/>
<DataGridTextColumn Header="Cr Head" Binding="{Binding CrHead}"/>
<DataGridTextColumn Header="Dr Amount" Binding="{Binding DrAmount}"/>
<DataGridTextColumn Header="Cr Amount" Binding="{Binding CrAmount}"/>
</DataGrid.Columns>
</DataGrid>
<Button Grid.Column="1" Content="Test" Click="Button_Click"/>
</Grid>
and in MainWindow.xaml.cs
, which you could move to a separate viewmodel if you wish, these:
public partial class MainWindow : Window
{
public Entry Selected { get; set; }
public ObservableCollection<Entry> Entries { get; set; }
public MainWindow() {
InitializeComponent();
Entries = new ObservableCollection<Entry>();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e) {
var win = new SecondWindow() { DataContext = Selected };
win.Show();
}
}
public class Entry
{
public string DrHead { get; set; }
public string CrHead { get; set; }
public int? DrAmount { get; set; }
public int? CrAmount { get; set; }
}
you also could convert that click event into an ICommand/Action
if you want. See in the event handler I've set the Selected
property, which is bound to the SelectedItem of DataGrid, of the MainWindow/ViewModel
as the DataContextof
SecondWindow. In the
SecondWindow.xaml` I've these:
<StackPanel>
<TextBox Text="{Binding DrHead}"/>
<TextBox Text="{Binding CrHead}"/>
<TextBox Text="{Binding DrAmount}"/>
<TextBox Text="{Binding CrAmount}"/>
</StackPanel>
When I run the App, this is what happens on button click:
EDIT
----
You can have a static Selected
property in your viewModel. I've moved the code into a separate viewModel, MainVM
, like this:
class MainVM
{
public static Entry Selected { get; set; }
public ObservableCollection<Entry> Entries { get; set; }
public Command ACommand { get; set; }
public MainVM() {
Entries = new ObservableCollection<Entry>();
ACommand = new Command(show, (o) => true);
}
void show(object o) {
var window = new SecondWindow();
window.Show();
}
}
and also moved the Entry
model in a separate Entry.cs
file. You can bind the static Selected
property in MainWindow
like this:
<Window x:Class="WPFTest.MainWindow"
...
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainVM />
</Window.DataContext>
<Grid Margin="20">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<DataGrid ItemsSource="{Binding Entries}"
SelectedItem="{Binding Selected}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Dr Head" Binding="{Binding DrHead}"/>
<DataGridTextColumn Header="Cr Head" Binding="{Binding CrHead}"/>
<DataGridTextColumn Header="Dr Amount" Binding="{Binding DrAmount}"/>
<DataGridTextColumn Header="Cr Amount" Binding="{Binding CrAmount}"/>
</DataGrid.Columns>
</DataGrid>
<Button Grid.Column="1" Content="Test" Command="{Binding ACommand}"/>
</Grid>
</Window>
and in SecondWindow
like this:
<Window x:Class="WPFTest.SecondWindow"
...
Title="SecondWindow" Height="450" Width="800">
<StackPanel DataContext="{Binding Path=(local:MainVM.Selected)}">
<TextBox Text="{Binding DrHead}"/>
<TextBox Text="{Binding CrHead}"/>
<TextBox Text="{Binding DrAmount}"/>
<TextBox Text="{Binding CrAmount}"/>
</StackPanel>
</Window>
this also will work.