Спасибо @GlennWatson за указание, что мне нужно добавить ссылку на пакет Nuget ReactiveUI.WPF
, в дополнение к пакету ReactiveUI
.
У меня есть ReactiveObject
модель представления, в которой я хотел бы использовать OpenFileDialog
, чтобы установить значение одного из моих свойств модели представления (PdfFilePath
).
Все, что я пробовал, приводит к ошибке The calling thread cannot access this object because a different thread owns it
.
Я понимаю, что приведенный ниже код не совместим с MVVM, потому что я использую код, который «явно ссылается на тип / создает представление» в модели представления, но я просто ищу минимальный пример, который работает, чтобы я мог работать в обратном направлении, разделяя представление и код модели представления и, в конечном счете, передавая сервис моей модели представления, которая обрабатывает всю часть «выбор пути к файлу».
public class ImportPdfViewModel : ReactiveObject
{
public ImportPdfViewModel()
{
SelectFilePathCommand = ReactiveCommand.Create(() =>
{
OpenFileDialog ofd = new OpenFileDialog() { };
//
if (ofd.ShowDialog() == DialogResult.OK)
PdfFilePath = ofd.FileName;
});
}
private string _PdfFilePath;
public string PdfFilePath
{
get => _PdfFilePath;
set => this.RaiseAndSetIfChanged(ref _PdfFilePath, value);
}
public ReactiveCommand SelectFilePathCommand { get; set; }
}
Как я уже упоминал, я пробовал множество различных опций, включая внедрение службы в мою модель представления, но независимо от того, где я создаю экземпляр OpenFileDialog
(например, в главном представлении), я всегда получаю одну и ту же ошибку .
Я также погуглил "ReactiveUI" и "OpenFileDialog", но, похоже, ни один из кодов, которые я нашел, не устарел (например, с использованием ReactiveCommand<Unit, Unit>
) и не соответствует ни одному другому примеру! Спасибо.
UPDATE
Спасибо @GlennWatson за указание на то, что мне нужно добавить ссылку на пакет Nuget ReactiveUI.WPF
, в дополнение к пакету ReactiveUI
.
Как только я его добавил, код заработал!
Код теперь выглядит следующим образом, который, я считаю, совместим с MVVM, использует внедрение зависимостей и использует новейшие функции / лучшие практики ReactiveUI (хотя я, очевидно, открыт для критики!):
ImportPdf
public class ImportPdfViewModel : ReactiveObject
{
public ImportPdfViewModel(IIOService openFileDialogService)
{
SelectFilePathCommand = ReactiveCommand
.Create(() => openFileDialogService.OpenFileDialog(@"C:\Default\Path\To\File"));
SelectFilePathCommand.Subscribe((pdfFilePath) => { PdfFilePath = pdfFilePath; });
}
private string _PdfFilePath;
public string PdfFilePath
{
get => _PdfFilePath;
set => this.RaiseAndSetIfChanged(ref _PdfFilePath, value);
}
public ReactiveCommand<Unit, String> SelectFilePathCommand { get; set; }
}
IIOService
public interface IIOService
{
string OpenFileDialog(string defaultPath);
}
OpenFileDialogService
public class OpenFileDialogService : IIOService
{
public string OpenFileDialog(string defaultPath)
{
OpenFileDialog ofd = new OpenFileDialog() { FileName = defaultPath };
//
if (ofd.ShowDialog() == DialogResult.OK)
{
return ofd.FileName;
}
else
{
return null;
}
}
}
UPDATE
У меня также была ошибка ниже, вызванная тем же отсутствующим пакетом ... This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread