같은 ViewModel에서 여러 다른 xaml을 설정할 수 있나요?

안녕하세요, 오랜만에 글을 쓰네요. 다른 업무로 바쁘다가 다시 wpf 프로젝트를 잡고 하고 있습니다. 이제 어느정도 하다보니까 요령?이란것이 생겨서 어찌어찌 하고 있는데요.
아무래도 하면서도 좀 더 괜찮은 방법이 있지 않을까 해서 닷넷데브에 한번 올려봅니다 ㅎㅎ…

아래 예시코드 처럼 DisplayViewModel 에다가 AnalCamViewModel을 넘겨주고 있는데요.
view:AnalCam 이란 view 말고도 다른 view들을 ViewModel에다가 할당하고 싶은데 다 따로 별도의 ViewModel을 선언해주고 DataTemplate으로 선언해놓고 사용해야 하나요?

현재코드

<UserControl.Resources>
        <DataTemplate DataType="{x:Type vm:AnalCamViewModel}">
            <view:AnalCam/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:PictureViewModel}">
            <view:PicturePage />
        </DataTemplate>
</UserControl.Resources>
<Grid Background="Black">
     <ContentControl Content="{Binding DisplayViewModel}"></ContentControl>
</Grid>

생각해본 코드

<UserControl.Resources>
        <DataTemplate DataType="{x:Type vm:AnalCam1ViewModel}">
            <view:AnalCam1/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:AnalCam2ViewModel}">
            <view:AnalCam2/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:PictureViewModel}">
            <view:PicturePage />
        </DataTemplate>
</UserControl.Resources>
<Grid Background="Black">
     <ContentControl Content="{Binding DisplayViewModel}"></ContentControl>
</Grid>

이게 페이지를 작업하다보면 90% 동일한 UI에 10%만 다른 페이지들이 생기기 마련인데 일단은 제가 하는 방식은 다르게 표현해야 하는 UI를 Grid같은걸로 감싸고 Visibility를 Viewmodel에다가 바인딩해놓고 생성자에서 1번이면 Hidden 하고 2번이면 Visible 하는 방식으로 하였는데 이게 뭔가 화면을 제어하는건 맞는데 실시간으로 제어하는것도 아니고 최초에 구분만 지어주면 되는건데 바인딩하는게 좀 이상하기도 하고…

그래서 생각한게 xaml을 구분해놓고 쓰는게 어떤가 했는데 이건 또 Viewmodel을 각자 선언해줘야하는건가 싶네요.

다른분들은 어떻게 작업하시는지 여쭙니다!

2개의 좋아요

질문이 잘 이해가 되지 않습니다.

View에 해당 ViewModel 타입을 사용하겠다는 의미이죠?

어떻게 구현되던 최종 화면이 제대로 표현된다면 잘못된 방식은 아니라고 생각합니다.


제가 질문이 잘 이해가 안되어 정확한 답은 드리기 힘들지만 조금 도움이 될 수 있도록…

여러 View에서 동일 ViewModel을 사용할 수 있는가? 사용해도 되는가? 의 질문이라면 당연히 됩니다.
다만 복수개의 View가 사용하는 동일 ViewModel과의 상관 관계는 있어야겠지요.

좀 더 구체적인 정보가 필요하시면 댓글로 궁금한 점을 하나씩 물어봐 주세요.

2개의 좋아요

네, 여러 View에서 동일 ViewModel을 사용한다기보다도 약간 다릅니다.
아래 처럼 ContentControlDisplayViewModel을 바인딩해서 원하는 뷰모델을 바꿔가면서 쓰고 있습니다.

<ContentControl Content="{Binding DisplayViewModel}"></ContentControl>
DisplayViewModel = new AnalCamViewModel();
or
DisplayViewModel = new PictureViewModel();

위 상황에서 AnalCamViewModel에 연결해야할 View가 2개가 있는 경우입니다.

AnalCam1.xaml, AnalCam2.xaml 2개를
AnalCamViewModel.cs 뷰모델에 연결하고 싶은데 제가 아는 방법으로는 아래 코드 처럼
ViewModel을 각각 별도로 선언해서 연결하는 방법입니다.
근데 이러면 거의 중복되는 뷰코델 클래스를 2개 선언해야 하는 상황이니까
(AnalCam1ViewModel.cs, AnalCam2ViewModel.cs)
다른 방법이 있지 않을까 싶어서 질문드렸습니다.

<DataTemplate DataType="{x:Type vm:AnalCam1ViewModel}">
      <view:AnalCam1/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:AnalCam2ViewModel}">
      <view:AnalCam2/>
</DataTemplate>
1개의 좋아요

우선 제가 이해한 질문 내용은 이렇습니다.

UI가 90%가 동일하고 나머지 10%가 다른 View를 어떻게 효율적으로
View ↔ ViewModel과 상관관계를 처리하는게 좋을지에 대한 고민 같습니다.

제가 이해한것이 맞다면

공통으로 사용되는 90% UI에 대한 View를 만들고 나머지 10% 에 해당되는 View는 각 개별적으로 만들어 처리합니다.

<UserControl.Resources>
        <DataTemplate DataType="{x:Type vm:공통ViewModel}">
            <view:공통View/>
        </DataTemplate>

        <DataTemplate DataType="{x:Type vm:AnalCam1ViewModel}">
            <view:10%다른뷰1/>
        </DataTemplate>

        <DataTemplate DataType="{x:Type vm:AnalCam2ViewModel}">
            <view:10%다른뷰2/>
        </DataTemplate>
</UserControl.Resources>

공통 View 안에서

<ContentControl Content="{Binding Fragment}"/>

이런식으로 일부 UI만 ContentControl로 Fragment처럼 구성시키면 될 것 같습니다.

공통 뷰모델과 Fragment에 해당되는 뷰모델 서로간 데이터 전달이 필요한 경우에는 메 이벤트어그리게이트 패턴을 활용한 메신저 같은 기능을 구현해서 처리하면 될 것 같구요.

즉 전체 View에서 일부 UI를 동적으로 변하게 하는 것이 목표인 것 같습니다.

* 혹시나 ListBox나 ListView 같은 바인딩된 데이터의 가시적인 UI가 상황에 따라 바뀌는것이 목표라면
데이터템플릿셀렉터 를 이용하면 됩니다.

3개의 좋아요

답변감사합니다.
90% 동일한 UI와 10% UI만 분리하는 방법도 있겠네요. 괜찮은 방법 같습니다.
다만, 그럼 3개의 각기 다른 ViewModel 클래스를 선언해야하는게 조금 걸리네요.
10%다른 뷰가 뭐 동작을 한다기보다 흰색 원이 있고 없고 라던가, 텍스트가 조금 다르다던가 그런거라…

그런데 2분 답변보고 곰곰히 생각하니 제가 효율을 따지자고 한게 약간 모순적이네요…
저는 ViewModel 에서 달라져야 하는 UI의 Visibilty 속성을 바인딩하고 해당 UI를 on/off 하는게 썩 맘에 안들어서 어차피 UI적으로도 조금씩 다르니 View xaml이 분리되면 좋겠다고 생각했었습니다.
근데 생각해보면 2개의 View 코드도 중복된 코드에 10%정도만 다른 코드이니
ViewModel이 2개 생성되서 비효율이라고 말하나 그게 그거겠네요 ㅎㅎ;;;

그래도 제기준? 에서 View가 분리되어 있는게 좋을거 같기도 합니다…

1개의 좋아요

효율성을 따지는거에 있어서

클래스 개수가 늘어나는것 보단 중복코드가 있는지 없는지에 봐야 합니다.

각 역할이 분명한 화면이라면 각기 다른 ViewModel을 만드는것이 당연하겠죠

차후 유지보수때 저 요구사항이 변경되지 않는게 확실하다면 (갑자기 많은 기능이 추가된다던가 전혀 다른 기능이 추가된다던가 이런게 아니라면)

굳이 UI를 파편화 하고 그게 맞는 뷰모델을 생성 할 필요 없이
그냥 바인딩과 컨버터 만으로 또는 트리거등 으로 동적 UI 처리를 하는게 더 좋아 보입니다.

3개의 좋아요