Доброго времени суток господа эксперты. Подскажите пожалуйста новичку в WPF. В главном окне есть кнопка открытия диалогового окна формы. Как после заполнения полей вернуть эти данные в главное окно для последующего сохранения в бд и обновления списка? Не смог найти подходящей реализации. Ниже код приложения. Сразу не кидайте палки и камни, код приложения тестовый поэтому здесь сумбур, создал для понимания процесса из него буду собирать нормальное , когда приведу в порядок все операции CRUD.Заранее спасибо за помощь.
Главное окно RecordsWindowView
public partial class RecordsWindowView : Window
{
public RecordsWindowView()
{
InitializeComponent();
DataContext = new RecordsViewModel();
}
}
Вьюмоделька:
public class RecordsViewModel : ViewModelBase
{
private Article _selectedRecord;
public Article SelectedRecord
{
get { return _selectedRecord; }
set
{
_selectedRecord = value;
OnPropertyChanged("SelectedRecord");
}
}
public RecordsViewModel()
{
LoadData();
}
private void LoadData()
{
using (AppDbContext context = new AppDbContext())
{
var listRecords = context.News.ToList();
_records = new ObservableCollection<Article>(listRecords);
}
}
private ObservableCollection<Article> _records { get; set; }
public ObservableCollection<Article> Records
{
get { return _records; }
set
{
_records = value;
OnPropertyChanged("CollectionCar");
}
}
private ICommand _addNewItemCommand;
public ICommand AddNewItemCommand =>
_addNewItemCommand ?? (_addNewItemCommand = new MyCommand(AddFormRecord));
private async void AddFormRecord(object obj)
{
AddFormView addRecordWindow = new AddFormView();
if (addRecordWindow.ShowDialog() == true)
{
var newRecord = (AddFormVM)addRecordWindow.DataContext;
using (AppDbContext context = new AppDbContext())
{
await context.News.AddAsync(newRecord.Record);
await context.SaveChangesAsync();
}
}
}
}
Диалоговое окно формы:
public partial class AddFormView : Window
{
// public Article Record { get; set; }
public AddFormView()
{
InitializeComponent();
//Record = rec;
//DataContext = Record;
DataContext = new AddFormVM ();
}
private void Accept_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
}
Вторая вьюмодель:
public class AddFormVM : ViewModelBase
{
private Article _record;
public Article Record
{
get { return _record; }
set
{
_record = value;
OnPropertyChanged("SelectedRecord");
}
}
}
Базовая модель:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
// PropertyChanged получает свойство из окна xlm какогото поля и обновляет событие
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}
Главное окно со списком записей:
<Window x:Class="WpfAppTEST_dot_NET5_ICommand_SQL.Views.RecordsWindowView"
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:WpfAppTEST_dot_NET5_ICommand_SQL.Views"
xmlns:vmodels="clr-namespace:WpfAppTEST_dot_NET5_ICommand_SQL.ViewModels"
mc:Ignorable="d"
Title="RecordsWindowView" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" >
<DataGrid
ItemsSource="{Binding Records, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
SelectedItem="{Binding SelectedRecord}"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="True"
>
<DataGrid.Columns >
<DataGridTextColumn Width="*" Header="ID" Binding="{Binding ArticleId}" FontFamily="Arial" FontStyle="Italic" />
<DataGridTextColumn Width="*" Header="TITLE" Binding="{Binding Title}" FontFamily="Arial" FontStyle="Italic" />
<DataGridTextColumn Width="*" Header="TITLE" Binding="{Binding Title}" FontFamily="Arial" FontStyle="Italic" />
<DataGridTextColumn Width="*" Header="DECRIPTION" Binding="{Binding Descripton}" FontFamily="Arial" FontStyle="Italic" />
<DataGridTextColumn Width="*" Header="CATEGORY" Binding="{Binding Category}" FontFamily="Arial" FontStyle="Italic" />
<DataGridTextColumn Width="*" Header="AUTHOR" Binding="{Binding Author}" FontFamily="Arial" FontStyle="Italic" />
<DataGridTemplateColumn Width="*" Header="ACTIONS">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
CommandParameter="{Binding}"
Content="DELETE"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
Диалоговое окно формы:
<Window x:Class="WpfAppTEST_dot_NET5_ICommand_SQL.Views.AddFormView"
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:WpfAppTEST_dot_NET5_ICommand_SQL.Views"
mc:Ignorable="d"
Title="AddFormView" Height="450" Width="800">
<Grid Margin="10" >
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" DataContext="{Binding Record}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Название" />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Record.Title}" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Описание" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Record.Descripton}" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Полный текст" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Record.FullText}" />
<TextBlock Grid.Row="3" Grid.Column="0" Text="Категирия" />
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Record.Category}" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="Автор" />
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Record.Author}" />
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Grid.Row="5" Grid.ColumnSpan="2">
<Button IsDefault="True" Click="Accept_Click" MinWidth="60" Margin="5">OK</Button>
<Button IsCancel="True" MinWidth="60" Margin="5">Отмена</Button>
</StackPanel>
</Grid>
</Grid>
Click, что тоже в MVVM не есть хорошо, ибо все события там наICommand. MVVM - это абстракции и минимальная связь всего. – EvgeniyZ Jan 25 '22 at 21:17AddFormView addRecordWindow = new AddFormView();сделайтеaddRecordWindow.DataContext = ...;, а из конструктора уберите, само значениеDataContextвынесите в отдельное свойство, к которому будете иметь доступ, ну и дальше дергайте из нее что хотите. Ну либо сделайте метод, который вернет вам результат (а-ляvar result = addRecordWindow.DoSome();, но это я думаю понимаете, что все является костылями. Ну а примерно такое у вас должно быть. – EvgeniyZ Jan 25 '22 at 21:22У меня за логику отвечают 2 VM- да, а кто отвечает за эти VM? Кто их создает? Помним правило MVVM, где "View слой не должен знать про VM и М, а VM не должен знать про View", нарушено ли оно у вас? Вот если к примеру удалить классRecordsViewModel, запустится ли приложение с пустым UI? Нет. Почему? А потому, что оно тесно связано с этим классом. Почитайте это.Не могли бы вы показать- так я вроде уже показал, не? – EvgeniyZ Jan 25 '22 at 21:46