Спасибо @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>) и не согласуется с каким-либо другим примером! Спасибо.


ОБНОВИТЬ

Спасибо @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;
        }
    }
}

ОБНОВИТЬ

У меня также была указанная ниже ошибка, вызванная тем же отсутствующим пакетом ... This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread

6
3-14159265358979323846264 6 Ноя 2018 в 14:03

1 ответ

Лучший ответ

Если вы работаете на платформе WPF или WinForms, вам необходимо убедиться, что вы включили ссылку nuget на ReactiveUI.WPF или ReactiveUI.Winforms.

4
Glenn Watson 13 Ноя 2018 в 21:37