0

Доброго времени суток господа эксперты. Подскажите пожалуйста новичку в 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&lt;Article&gt; Records
{
    get { return _records; }
    set
    {
        _records = value;
        OnPropertyChanged(&quot;CollectionCar&quot;);
    }
}

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(&quot;SelectedRecord&quot;);
    }
}

}

Базовая модель:

  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>
&lt;Grid.RowDefinitions&gt;
    &lt;RowDefinition Height=&quot;*&quot;/&gt;
    &lt;RowDefinition Height=&quot;*&quot;/&gt;
    &lt;RowDefinition Height=&quot;*&quot;/&gt;            

&lt;/Grid.RowDefinitions&gt;

&lt;Grid Grid.Row=&quot;0&quot;  &gt; 

    &lt;DataGrid                     
        ItemsSource=&quot;{Binding  Records, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}&quot;
        SelectedItem=&quot;{Binding SelectedRecord}&quot;
        AutoGenerateColumns=&quot;False&quot;
        CanUserAddRows=&quot;False&quot; 
        IsReadOnly=&quot;True&quot;

        &gt;
        &lt;DataGrid.Columns &gt;
            &lt;DataGridTextColumn  Width=&quot;*&quot;  Header=&quot;ID&quot; Binding=&quot;{Binding ArticleId}&quot; FontFamily=&quot;Arial&quot; FontStyle=&quot;Italic&quot; /&gt;
            &lt;DataGridTextColumn   Width=&quot;*&quot;  Header=&quot;TITLE&quot; Binding=&quot;{Binding Title}&quot; FontFamily=&quot;Arial&quot; FontStyle=&quot;Italic&quot; /&gt;
            &lt;DataGridTextColumn  Width=&quot;*&quot;  Header=&quot;TITLE&quot; Binding=&quot;{Binding Title}&quot; FontFamily=&quot;Arial&quot; FontStyle=&quot;Italic&quot; /&gt;
            &lt;DataGridTextColumn  Width=&quot;*&quot;   Header=&quot;DECRIPTION&quot; Binding=&quot;{Binding Descripton}&quot; FontFamily=&quot;Arial&quot; FontStyle=&quot;Italic&quot; /&gt;
            &lt;DataGridTextColumn  Width=&quot;*&quot;  Header=&quot;CATEGORY&quot; Binding=&quot;{Binding Category}&quot; FontFamily=&quot;Arial&quot; FontStyle=&quot;Italic&quot; /&gt;
            &lt;DataGridTextColumn  Width=&quot;*&quot;  Header=&quot;AUTHOR&quot; Binding=&quot;{Binding Author}&quot; FontFamily=&quot;Arial&quot; FontStyle=&quot;Italic&quot; /&gt;

            &lt;DataGridTemplateColumn  Width=&quot;*&quot;  Header=&quot;ACTIONS&quot;&gt;
                &lt;DataGridTemplateColumn.CellTemplate&gt;
                    &lt;DataTemplate&gt;

                            &lt;Button 
                            Command=&quot;{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}&quot;  
                            CommandParameter=&quot;{Binding}&quot;
                            Content=&quot;DELETE&quot;/&gt;

                    &lt;/DataTemplate&gt;
                &lt;/DataGridTemplateColumn.CellTemplate&gt;
            &lt;/DataGridTemplateColumn&gt;               
        &lt;/DataGrid.Columns&gt;
    &lt;/DataGrid&gt;
&lt;/Grid&gt;

Диалоговое окно формы:

<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"/>
&lt;/Grid.RowDefinitions&gt;

&lt;Grid Grid.Row=&quot;1&quot; DataContext=&quot;{Binding Record}&quot;&gt;
    &lt;Grid.RowDefinitions&gt;
        &lt;RowDefinition Height=&quot;auto&quot;/&gt;
        &lt;RowDefinition Height=&quot;auto&quot;/&gt;
        &lt;RowDefinition Height=&quot;auto&quot;/&gt;
        &lt;RowDefinition Height=&quot;auto&quot;/&gt;
        &lt;RowDefinition Height=&quot;auto&quot;/&gt;
        &lt;RowDefinition Height=&quot;auto&quot;/&gt;


    &lt;/Grid.RowDefinitions&gt;
    &lt;Grid.ColumnDefinitions&gt;
        &lt;ColumnDefinition Width=&quot;0.5*&quot; /&gt;
        &lt;ColumnDefinition Width=&quot;*&quot; /&gt;
    &lt;/Grid.ColumnDefinitions&gt;

    &lt;TextBlock  Grid.Row=&quot;0&quot; Grid.Column=&quot;0&quot; Text=&quot;Название&quot; /&gt;
    &lt;TextBox  Grid.Row=&quot;0&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding Record.Title}&quot; /&gt;
    &lt;TextBlock  Grid.Row=&quot;1&quot; Grid.Column=&quot;0&quot; Text=&quot;Описание&quot; /&gt;
    &lt;TextBox  Grid.Row=&quot;1&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding Record.Descripton}&quot; /&gt;
    &lt;TextBlock  Grid.Row=&quot;2&quot; Grid.Column=&quot;0&quot; Text=&quot;Полный текст&quot; /&gt;
    &lt;TextBox  Grid.Row=&quot;2&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding Record.FullText}&quot; /&gt;
    &lt;TextBlock  Grid.Row=&quot;3&quot; Grid.Column=&quot;0&quot; Text=&quot;Категирия&quot; /&gt;
    &lt;TextBox  Grid.Row=&quot;3&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding Record.Category}&quot; /&gt;
    &lt;TextBlock  Grid.Row=&quot;4&quot; Grid.Column=&quot;0&quot; Text=&quot;Автор&quot; /&gt;
    &lt;TextBox  Grid.Row=&quot;4&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding Record.Author}&quot; /&gt;
    &lt;StackPanel HorizontalAlignment=&quot;Center&quot; Orientation=&quot;Horizontal&quot; Grid.Row=&quot;5&quot; Grid.ColumnSpan=&quot;2&quot;&gt;
        &lt;Button  IsDefault=&quot;True&quot; Click=&quot;Accept_Click&quot; MinWidth=&quot;60&quot; Margin=&quot;5&quot;&gt;OK&lt;/Button&gt;
        &lt;Button IsCancel=&quot;True&quot; MinWidth=&quot;60&quot; Margin=&quot;5&quot;&gt;Отмена&lt;/Button&gt;
    &lt;/StackPanel&gt;
&lt;/Grid&gt;

</Grid>

  • Ваша проблема в том, что у вас нету MVVM. У вас окно отвечает за VM слой, создает его, управляет сроком жизни и т.д., когда по правилам MVVM, View слой должен быть максимально отделен от других, оно не должно знать, что где-то там есть некий класс, в котором свойство ..., из которого надо взять данные. Также и наоборот, VM слой не должен знать что-либо о View, он должен лишь взять данные из Model, сделать нужные свойства для привязки, все. Ну и также, вы делаете Click, что тоже в MVVM не есть хорошо, ибо все события там на ICommand. MVVM - это абстракции и минимальная связь всего. – EvgeniyZ Jan 25 '22 at 21:17
  • Ну а так, если хотите ваш код заставить работать, то после строки AddFormView addRecordWindow = new AddFormView(); сделайте addRecordWindow.DataContext = ...;, а из конструктора уберите, само значение DataContext вынесите в отдельное свойство, к которому будете иметь доступ, ну и дальше дергайте из нее что хотите. Ну либо сделайте метод, который вернет вам результат (а-ля var result = addRecordWindow.DoSome();, но это я думаю понимаете, что все является костылями. Ну а примерно такое у вас должно быть. – EvgeniyZ Jan 25 '22 at 21:22
  • Извините, но я вас не совсем понял. У меня за логику отвечают 2 VM (RecordsViewModel и AddFormVM) . Их я и передам в контекст в конструкторе окон AddFormView и RecordsWindowView. В коде окон у меня никакой логики нет, ну кроме клика в диалоговом. Не могли бы вы показать пример правильной реализации mvvm и передачи данных между окнами. – Zerg Zerg Jan 25 '22 at 21:32
  • У меня за логику отвечают 2 VM - да, а кто отвечает за эти VM? Кто их создает? Помним правило MVVM, где "View слой не должен знать про VM и М, а VM не должен знать про View", нарушено ли оно у вас? Вот если к примеру удалить класс RecordsViewModel, запустится ли приложение с пустым UI? Нет. Почему? А потому, что оно тесно связано с этим классом. Почитайте это. Не могли бы вы показать - так я вроде уже показал, не? – EvgeniyZ Jan 25 '22 at 21:46
  • Спасибо большое за ваш ответ, попытаюсь все поправить на основе ваших рекомендаций. – Zerg Zerg Jan 25 '22 at 22:04

0 Answers0