Как открыть окно WPF в режиме AddNew до загрузки каких-либо данных? - PullRequest
1 голос
/ 02 февраля 2011

Я хочу открыть форму WPF4 / EF4 в режиме AddNew, чтобы пользователь мог начать вводить данные в связанных элементах управления до того, как какие-либо данные были выбраны из базы данных.У меня уже есть кнопка «Добавить новую запись», но она работает только с заполненным DataContext (мой CollectionViewSource).Вот код на данный момент:

private void btnAddNewRecord_Click(object sender, RoutedEventArgs e)
{
    LabSample newEntity = _labEntitiesContext.LabSamples.CreateObject<LabSample>();
    _labEntitiesContext.LabSamples.AddObject(newEntity);
    _labSamplesListCollectionView.AddNewItem(newEntity);
}

Справочная информация: Это базовое приложение WPF со связанными элементами управления.Я начал с модели Entity Framework, которая появляется в моем окне источников данных.Я перетащил свой объект LabSample из окна DataSources и позволил ему создать мой CollectionViewSource (labSamplesViewSource) в разделе XAML Windows.Resources.DataContext для всех моих элементов управления - labSamplesViewSource.Я создаю новый объект LabEntities с именем _labEntitiesContext, когда создается окно.Я использую _labEntitiesContext для создания моего отфильтрованного ObjectQuery (из LabSample) и SaveChanges, но я немного запутался, как этот _labEntitiesContext подключен к моему CollectionViewSource.Если бы вы могли уточнить это вместе с ответом на мой вопрос, это было бы полезно. Примечание: Я не готов использовать MVVM.

Когда загружается окно, я использую this.FindResource для получения ссылки на CollectionViewSource в переменной уровня класса с именем _labSamplesCollectionViewSource.Я разрешаю пользователю вводить поля поиска, чтобы заполнить экран данными.Моя подпрограмма LoadData выглядит примерно так:

System.Data.Objects.ObjectQuery<LabSample> labSamplesObjectQuery = this.GetLabSamplesFiltered_Query(_labEntitiesContext, sampleID_LIKE, xxx_LIKE, yyy_LIKE);
System.Data.Objects.ObjectResult<LabSample> labSamplesObjectResult = labSamplesObjectQuery.Execute(System.Data.Objects.MergeOption.AppendOnly);
_labSamplesCollectionViewSource.Source = new System.Collections.ObjectModel.ObservableCollection<LabSample>(labSamplesObjectResult);
_labSamplesListCollectionView = (ListCollectionView)_labSamplesCollectionViewSource.View;

Переменная уровня класса _labSamplesListCollectionView, указанная выше, используется в моем коде btnAddNewRecord_Click. Перед вызовом LoadData _labSamplesListCollectionView имеет значение null, что приводит к сбою моего кода AddNew с «Ссылка на объект не установлена ​​для экземпляра объекта».

Как я могу заставить эту работу?Мне интересно, должен ли я использовать _labSamplesListCollectionView.AddNew вместо моей нынешней техники, но я тоже не смог получить эту работу.Ваша помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2011

Вместо открытия окна в режиме AddNew я отключаю все элементы управления вводом данных, когда окно загружается или когда поиск не возвращает записей.Когда нажата кнопка «Добавить новую запись», я ВСЕГДА начинаю заново с новым контекстом данных, который содержит только одну новую сущность.Это означает, что я должен предложить сохранить изменения, если существуют какие-либо грязные (измененные) записи.Подсказка позволяет пользователю сохранять изменения, отменять изменения или продолжать редактирование (никогда не переходя в режим AddNew).Вот код AddNew:

MessageBoxResult response = PromptToSaveChanges(ReasonForPromptToSave.LoadingData);

if (response == MessageBoxResult.Cancel)  return;           

LabSample newEntity = _labEntitiesContext.LabSamples.CreateObject<LabSample>();
_labEntitiesContext.LabSamples.AddObject(newEntity);

_labSamplesCollectionViewSource.Source = new ObservableCollection<LabSample>();
_labSamplesListCollectionView = (ListCollectionView)_labSamplesCollectionViewSource.View;

_labSamplesListCollectionView.AddNewItem(newEntity);
_labSamplesListCollectionView.CommitNew();
_labSamplesListCollectionView.Refresh();

Вот мои шаги, чтобы перевести окно в режим AddNew:

1) Запросить сохранение изменений.

2) СоздатьНовая сущность и добавьте ее в мой контекст данных.

3) Создайте новую коллекцию ObservableCollection моего типа сущности и назначьте ее для .Source моего CollectionViewSource.Обратите внимание, что _labSamplesCollectionViewSource является ссылкой на CollectionViewSource XAML, который был автоматически создан путем перетаскивания таблицы из окна источников данных.

4) Присвойте .View объекта CollectionViewSource переменной уровня ListCollectionView уровня класса.

5) Добавить новую сущность в только что созданный ListCollectionView.

6) Вызвать CommitNew и обновить в ListCollectionView

Я ответил на свой вопрос здесь, но имейте в видучто ответ является результатом проб и ошибок и может быть не идеальным.Что касается моей путаницы относительно того, как _labEntitiesContext подключен к CollectionViewSource, я считаю, что ответ находится в строке, которая читает _labSamplesListCollectionView.AddNewItem (newEntity), но я хотел бы увидеть объяснение того, как все объекты ссылаются друг на друга.

Мой последний комментарий / вопрос заключается в том, что я разочарован тем, насколько сложно найти стандартное эталонное приложение или документ, в котором подробно описывается привязка данных не из MVVM WPF / Entity Framework.Microsoft продвигает привязку методом перетаскивания, но оставляет нас без ссылки на то, как создать законченное приложение.Вскоре я перейду к MVVM, и если кто-нибудь сможет направить меня к БОЛЬШОМУ ресурсу или полнофункциональному приложению, которое является WPF, не-MVVM и Entity Framework, я был бы очень признателен.

0 голосов
/ 02 февраля 2011

Я пишу приложение, которое делает что-то подобное. Я, однако, использую шаблон MVVM, который позволяет мне делать некоторые изящные вещи. По моему я работаю с отгрузками. На ShipmentsView я могу нажать кнопку «Добавить новый», которая запускает привязанное свойство команды, которое находится в связанном классе ViewModel. Методы этой команды выглядят следующим образом: Примечание. Представления в этом контексте не являются CollectionView, но ссылаются на классы представления MVVM.

Dim NewShipment = New Shipment()
_Context.AddToShipments(NewShipment)
Dim ShipVM = New ShipmentViewModel(NewShipment)
ShipmentVMCollection.Add(ShipVM)
Dim NewShipmentView as ShipmentView(ShipVM)

Мой ShipmentView обрабатывает его размещение и видимость, а мой объект Shipment имеет свои значения свойств, инициализированные так, что он не сразу представляет ошибки через свои обработчики проверки. Таким образом, пользователь может создать новый груз и, если его отвлекли, он может сохранить его и вернуться к нему, не имея набора обязательных полей.

Когда я использую CollectionViewSource, я заполняю его ObservableCollection моих сущностей, а затем добавляю сущности в эту наблюдаемую коллекцию, когда создаю их. ObservableCollection реализует события INotifyPropertyChanged и INotifyCollectionChanged и уведомляет пользовательский интерфейс, когда что-то происходит, и все это работает через CollectionViewSource.

Вы можете взглянуть на шаблон MVVM, который действительно хорош для перемещения данных и поддержания его в нужном объеме, и есть несколько хороших сред MVVM, которые помогут вам сделать хорошее приложение с MVVM.

MVVM может быть немного излишним для вашего приложения, если оно маленькое. Но если он преодолеет больше, чем несколько видов, он станет громоздким и трудным для перемещения данных вперед и назад и поддержания их актуальности и удобства обслуживания.

Статья Wiki для MVVM - довольно хорошее место для начала и получения ссылок

Это мой конструктор для одной из моих моделей представления. Я понимаю, что вы не хотите внедрять в MVVM прямо сейчас, но код будет похожим. В этом случае я использую фонового работника для получения моих записей сущностей (вызов конструктора для этого и настройки View сразу же можно игнорировать), затем я связываю свой CVS, заполняю его с помощью ObservableCollection и устанавливаю его Просмотр поля, чтобы я мог отфильтровать его позже.

Public Sub New(ByRef MyView As NTMsView)
    Me.New(ViewManagerService.CreateInstance, ViewModelUIService.CreateInstance)
    NTMsBackgroundWorker.RunWorkerAsync()
    _View = MyView
    _NTMCollectionViewSource = _View.FindResource("NTMCollectionViewSource")
    _NTMCollectionViewSource.Source = NTMs
    _NTMCollectionView = _NTMCollectionViewSource.View
End Sub

Это пример моего метода AddRecord. Затем я создаю экземпляр нового объекта, добавляю его в соответствующую коллекцию в контексте, сохраняю, выполняю хранимую процедуру, а затем обновляю контекст, поскольку хранимая процедура сделала несколько вещей с записью. Затем я добавляю объект в Observable.

Private Sub AddNTM()
    'Create an NTM Object.  
    Dim NewNTM As New NTMShipment()
    'Add it to the context
    _context.AddToNTMShipments(NewNTM)
    _context.SaveChanges()
    _context.MakeNewSecurityID(NewNTM.NTMShipID)
    _context.Refresh(RefreshMode.StoreWins, NewNTM)
    'Wrap it in a ViewModel and Add it to the NTMs collection
    NTMs.Add(New NTMViewModel(NewNTM))
End Sub

Что касается создания новой сущности до создания вашего CollectionViewSource, пара вопросов. Связан ли ваш текст редактирования форм с CVS? В моих формах CVS используется только в сочетании с ItemsControls, поскольку он отображает коллекцию элементов. Если ваши элементы управления формами редактирования отделены от CVS, у вас не должно возникнуть особых проблем с заполнением их новой сущностью, и когда придет время сохранять, проверьте, является ли CVS нулевым, и если это так, создайте его, а затем заполните его.

Если это не очень хороший ответ, не могли бы вы рассказать, как структурировано ваше приложение?

...