ActiveX в приложении WPF MVVM Light - PullRequest
0 голосов
/ 29 мая 2020

Я новичок в программировании C# WPF и работаю над WPF-приложением, которое должно включать устаревший компонент ActiveX. Я знаю, что ActiveX мертв, но, к сожалению, мне приходится использовать его в этом случае. Я использую MVVM Light с IFrameNavigationService, как показано в этом посте .

Кроме того, я использовал этот пример , чтобы привязать компонент ActiveX в представлении к следуйте рекомендациям MVVM, что, на мой взгляд, не лучший способ.

При каждой навигации мне приходится ждать, пока страница загрузится, чтобы подключиться к компоненту ActiveX (VideoService). Операция подключения занимает около 5 секунд. Таким образом, пользователю приходится долго ждать, чтобы использовать страницу, что, очевидно, плохо.

Теперь у меня есть два вопроса:

  1. Как бы вы включаете компонент ActiveX в шаблон MVVM? К сожалению, мне нужен VideoService для потоковой передачи видео, заданного VideoService в представлении, и мне нужно VideoService для запроса данных видео в ViewModel.

  2. Как Могу ли я использовать компонент ActiveX на каждой странице, не монтируя его при каждом изменении страницы?

Paint

Просмотр / Главный Windows .xaml

<Window x:Class="View.Desktop.MainWindow"
        ...
        DataContext="{Binding Main, Source={StaticResource Locator}}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding WindowLoadedCommand }" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <Frame x:Name="MainFrame" NavigationUIVisibility="Hidden" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
    </Grid>
</Window>

ViewModel / MainViewModel.cs

{
    public class MainViewModel : ViewModelBase
    {
        private readonly IFrameNavigationService navigationService;

        public RelayCommand WindowLoadedCommand { get; private set; }

        public MainViewModel(IFrameNavigationService navService)
        {
            navigationService = navService;

            WindowLoadedCommand = new RelayCommand(() =>
            {
                navigationService.NavigateTo("Home");
            });
        }
    }
}

Просмотр / Страницы / Главная .xaml

<Page x:Class="View.Desktop.Pages.HomePage"
      ...
      DataContext="{Binding HomeViewModel,Source={StaticResource Locator}}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding PageLoadedCommand }" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <ContentControl Content="{Binding VideoWindowsFormsHost}" />
        <Button Content="Navigate" Command="{Binding NavigateCommand}" />
    </Grid>
</Page>

ViewModel / HomeViewModel.cs

{
    public class HomeViewModel : ViewModelBase
    {
        private readonly IFrameNavigationService navigationService;

        readonly VideoService video;

        public WindowsFormsHost VideoWindowsFormsHost
        {
            get { return new WindowsFormsHost() { Child = video.v }; }
        }

        public ICommand PageLoadedCommand { get; private set; }
        public ICommand NavigateCommand { get; private set; }

        public HomeViewModel(IFrameNavigationService navService)
        {
            navigationService = navService;

            video = new VideoService();

            PageLoadedCommand = new RelayCommand(async () =>
            {
                // Very slow
                video.connect();
            });

            NavigateCommand = new RelayCommand(() =>
            {
                video.Disconnect();
                navigationService.NavigateTo("Settings");
            });
        }
    }
}

View / Pages / Settings.xaml

<Page x:Class="View.Desktop.Pages.SettingsPage"
      ...
      DataContext="{Binding SettingsViewModel,Source={StaticResource Locator}}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding PageLoadedCommand }" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <ContentControl Content="{Binding VideoWindowsFormsHost}" />
        <Button Content="Navigate" Command="{Binding NavigateCommand}" />
    </Grid>
</Page>

ViewModel / SettingsViewModel.cs

{
    public class SettingsViewModel : ViewModelBase
    {
        private readonly IFrameNavigationService navigationService;

        readonly VideoService video;

        public WindowsFormsHost VideoWindowsFormsHost
        {
            get { return new WindowsFormsHost() { Child = video.v }; }
        }

        public ICommand PageLoadedCommand { get; private set; }
        public ICommand NavigateCommand { get; private set; }

        public SettingsViewModel(IFrameNavigationService navService)
        {
            navigationService = navService;

            video = new VideoService();

            PageLoadedCommand = new RelayCommand(async () =>
            {
                // Very slow
                video.connect();
            });

            NavigateCommand = new RelayCommand(() =>
            {
                video.Disconnect();
                navigationService.NavigateTo("Home");
            });
        }
    }
}
...