XAML Design Time 에서 카메라 프리뷰가 나옵니다..

안녕하세요. 또 질문을 올리네요. 나름 열심히 구글링하다가 도저히 답이 안나와서 질문드립니다 ㅠㅠ

그리고 아래 글에서는 MainViewModel 에서 카메라 객체 선언해놓고 각기 다른 Usercontrol에다가 ImageSource를 Binding 하는 형태로 해서 진행하고 있습니다. 감사합니다~
MVVM 패턴에서 usercontrol 내 객체는 코드비하인드에 넣어야하나요?

제목 그대로 Build하고 Visual Studio가 켜져있는 상태에서 Program을 실행하면 카메라 프리뷰가 XAML Design Time 화면에 출력됩니다…

간혹 Program하고 연결되는 경우도 있으나 거의 대부분이 저쪽에 연결이 되네요… 심지어 Program하고 연결된 상태에서 Program을 끄면 다시 카메라가 껐다가 켜지면서 위 스크린샷처럼 다시 연결이 됩니다. 어떻게 보면 좋은 기능인거 같은데… 제 입장에선 Program에서 프리뷰가 안나오다보니 Test하기가 어렵네요

제가 뭔가 Viewmodel 연결을 잘 못했나 싶어서 관련 코드도 같이 올려드립니다.

MvvmLight 라이브러리 사용하여 ViewModelLocator에서 ViewModel들 등록해주었구요.
그다음 1분할, 2분할, 4분할 뷰가 있어야 해서 3개 View,ViewModel 선언한 후에 ContentControl Content에 Binding 해주었습니다.
ViewModel 같은 경우에는 원래 함수 호출시마다 new했으나 다른 코드 참조하여 아래와 같이 최초 초기화후 변경하는 걸로 수정하였습니다.
아 그리고 분할 ViewModel 쪽에 MainViewModel을 Parent로 보내주어 VideoFrame을 참조시키도록 하였습니다… 이렇게 해도 되나 싶긴하네요 ㅎㅎ;

일단 첫번째로 XAML Design Time에서 카메라 프리뷰가 연동되는 문제와 아래 코드처럼 View, Viewmodel을 처리해도 되는건지 궁금하네요. 미리 감사합니다!

[MvvmLight 라이브러리 사용]
public ViewModelLocator()
{
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

    if (ViewModelBase.IsInDesignModeStatic)
    {
        // Create design time view services and models
        //SimpleIoc.Default.Register<IDataService, DesignDataService>();
    }
    else
    {
        // Create run time view services and models
        //SimpleIoc.Default.Register<IDataService, DataService>();
    }
    SimpleIoc.Default.Register<MainViewModel>();
    SimpleIoc.Default.Register<CamviewOneViewModel>();
    SimpleIoc.Default.Register<CamviewTwoViewModel>();
    SimpleIoc.Default.Register<CamviewFourViewModel>();
    SimpleIoc.Default.Register<CapturelistViewModel>();
    SimpleIoc.Default.Register<CaptureitemViewModel>();
}
[MainWindow.xaml]
    <Window.DataContext>
        <Binding Source="{StaticResource Locator}" Path="Main"></Binding>
    </Window.DataContext>
...
    <Window.Resources>
        <DataTemplate DataType="{x:Type vm:CamviewOneViewModel}">
            <view:CamviewOne />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CamviewTwoViewModel}">
            <view:CamviewTwo />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CamviewFourViewModel}">
            <view:CamviewFour />
        </DataTemplate>
    </Window.Resources>
...
            <Viewbox Stretch="Uniform">
                <ContentControl 
                    Content="{Binding CamviewPage}">
                    
                </ContentControl>
            </Viewbox>
[MainViewModel.cs]
static CamviewOneViewModel camviewOneViewModel;
static CamviewTwoViewModel camviewTwoViewModel;
static CamviewFourViewModel camviewFourViewModel;

private ViewModelBase camviewPage;
public ViewModelBase CamviewPage
{
    get { return this.camviewPage; }
    set { this.camviewPage = value; this.RaisePropertyChanged(() => this.CamviewPage); }
}

public MainViewModel()
{
    ////if (IsInDesignMode)
    ////{
    ////    // Code runs in Blend --> create design time data.
    ////}
    ////else
    ////{
    ////    // Code runs "for real"
    ////}
    ///
    var availableMediaList = this.cameraDevice.GetVideoDevices;
    var selectedDevice = availableMediaList.FirstOrDefault();
    if (selectedDevice != null)
    {
        if (this.cameraDevice.InitCameraDevice(selectedDevice.UsbId))
        {
            this.cameraDevice.VideoCaptureDevice.SnapshotFrame += new NewFrameEventHandler(NewFrameSnapshot);
            this.cameraDevice.VideoCaptureDevice.NewFrame += new NewFrameEventHandler(NewFrameVideo);

            this.cameraDevice.Start();
            IsVideoSourceInitialized = true;
        }

    }

    MainViewModel.camviewOneViewModel = new CamviewOneViewModel(this);
    MainViewModel.camviewTwoViewModel = new CamviewTwoViewModel(this);
    MainViewModel.camviewFourViewModel = new CamviewFourViewModel(this);

}

private void OnClickCamViewOne()
{
    //CamviewPage = new CamviewOneViewModel(this);
    CamviewPage = MainViewModel.camviewOneViewModel;
}
private void OnClickCamViewTwo()
{
    //CamviewPage = new CamviewTwoViewModel(this);
    CamviewPage = MainViewModel.camviewTwoViewModel;
}
private void OnClickCamViewFour()
{
    //CamviewPage = new CamviewFourViewModel(this);
    CamviewPage = MainViewModel.camviewFourViewModel;
}

[CamviewOne.xaml]
<UserControl x:Class="HivePro.View.CamviewOne"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:HivePro.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.DataContext>
        <Binding Source="{StaticResource Locator}" Path="CamviewOne"></Binding>
    </UserControl.DataContext>
    <Grid x:Name="gridView" HorizontalAlignment="Stretch">
        <Grid x:Name="VideoSourceGrid" Visibility="{Binding VisibilityVideoGrid}" Background="Black">
            <Image Source="{Binding Parent.VideoFrame}"/>
        </Grid>
        <Grid x:Name="NoVideoSourceGrid" Background="LightGray" Visibility="{Binding VisibilityNoVideoGrid}">
            <Border BorderBrush="DimGray" BorderThickness="1">
                <TextBlock x:Name="NoVideoSourceMessage"
                           Text="{Binding TextNoVideo}"
                           VerticalAlignment="Top"
                           HorizontalAlignment="Center"
                           TextWrapping="Wrap"
                           FontSize="20"
                           FontWeight="Bold" />
            </Border>
        </Grid>
    </Grid>
</UserControl>
[CamviewOneViewModel.cs]
public class CamviewOneViewModel : ViewModelBase
{

private Visibility visibilityNoVideoGrid = Visibility.Visible;
public Visibility VisibilityNoVideoGrid
{
    get { return visibilityNoVideoGrid; }
    set { visibilityNoVideoGrid = value; RaisePropertyChanged(() => VisibilityNoVideoGrid); }
}
private Visibility visibilityVideoGrid = Visibility.Hidden;
public Visibility VisibilityVideoGrid
{
    get { return visibilityVideoGrid; }
    set { visibilityVideoGrid = value; RaisePropertyChanged(() => VisibilityVideoGrid); }
}
private string textNoVideo;
public string TextNoVideo
{
    get { return textNoVideo; }
    set { textNoVideo = value; RaisePropertyChanged(() => TextNoVideo); }
}
private readonly MainViewModel parent;
public MainViewModel Parent => parent;

public CamviewOneViewModel(MainViewModel parent)
{
    this.parent = parent;
    //VisibilityNoVideoGrid = Visibility.Hidden;
    //VisibilityVideoGrid = Visibility.Visible;
    //TextNoVideo = "No video source device found123";
    if (this.parent.IsVideoSourceInitialized)
    {
        VisibilityNoVideoGrid = Visibility.Hidden;
        VisibilityVideoGrid = Visibility.Visible;
        //VisibilityNoVideoGrid = Visibility.Visible;
        //VisibilityVideoGrid = Visibility.Hidden;
        TextNoVideo = "video ok";
    }
    else
    {
        VisibilityNoVideoGrid = Visibility.Visible;
        VisibilityVideoGrid = Visibility.Hidden;
        TextNoVideo = "No video source device found11";
        //TextNoVideo = "No video source device found11";
    }
}
}

좋아요 1

이미 class ViewModelLocator에 답이 나와있는데요?

public ViewModelLocator()
{
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

    if (ViewModelBase.IsInDesignModeStatic)
    {
        // Create design time view services and models
        //SimpleIoc.Default.Register<IDataService, DesignDataService>();
    }
    else
    {
        !!!----------- 여기다가 등록하세요. `SimpleIoc`에 등록할 때
        // Create run time view services and models
        //SimpleIoc.Default.Register<IDataService, DataService>();
    }
    SimpleIoc.Default.Register<MainViewModel>();
    SimpleIoc.Default.Register<CamviewOneViewModel>();
    SimpleIoc.Default.Register<CamviewTwoViewModel>();
    SimpleIoc.Default.Register<CamviewFourViewModel>();
    SimpleIoc.Default.Register<CapturelistViewModel>();
    SimpleIoc.Default.Register<CaptureitemViewModel>();
}
좋아요 2

감사합니다. 저도 그 부분이 걸리긴 해서 넣어보고 테스트했었는데 제가 착각했었나 보네요.
근데 어떻게 실행도 안했는데 카메라에 연결이 되죠!? 아직 모르는게 많네요 ㅠㅠ

좋아요 2

원래 모든 디자인뷰는 내부적으로 일부 코드를 러닝시키는 방식으로 나타내요.

해서 지금 같은 상황이 당연한 사례입니다.

좋아요 1

@SangHyeon.Kim 님 말씀처럼… 그렇습니다. 아마도 사용하신 MVVM 라이브러리가 Locator가 리소스라 디자인 타임에서도 인스턴스가 생성됩니다.

<Window.DataContext>
    <Binding Source="{StaticResource Locator}" Path="Main"></Binding>
</Window.DataContext>
좋아요 1