ActiveX in WPF MVVM Light application

那年仲夏 提交于 2020-06-01 07:40:38

问题


I am new to C# WPF programming and working on a WPF-Application that has to include a legacy ActiveX component. I know ActiveX is kind of dead but I have to use it in this case unfortunately. I use MVVM Light with an IFrameNavigationService as shown in this post.

Furthermore I used this example to bind the ActiveX component into the view to follow the guidlines of MVVM which is probalby not the best way in my opinion.

On each navigation I have to wait until page is loaded to connect with the ActiveX component (VideoService). The connecting operation takes about 5 seconds. So the user has to wait a long time to use the page which is obviously bad.

Now I got two questions:

  1. How would you include an ActiveX component into the MVVM pattern? Unfortunately I need the VideoService to stream a video given by the VideoService in the View and I need the VideoService to request data of the video in the ViewModel.

  2. How can I use the ActiveX component on every page without (un)mounting it on every page change?

View/MainWindows.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");
            });
        }
    }
}

View/Pages/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");
            });
        }
    }
}

来源:https://stackoverflow.com/questions/62082155/activex-in-wpf-mvvm-light-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!