winui3에서 page에 mvvm 방식으로 UserControl을 화면전환하면서 UI에 보여주려면 어떻게 해야할까요?

'닷넷네브’에서 .net을 개발하시는 모든 분들… 안녕하세요!

winui3 삽질 중인 주니어 개발자입니다…!

혹시 MVVM 방식을 이용하여 Page의 Frame 안에 UserControl을 그리려면 어떻게 코드를 작성해야하나요…?

SplitView를 이용하여 Navigation을 그렸고 Buttom의 Command를 이용하여 ListView에서 Item의 Button 클릭시 mainFrame 부분의 화면을 Usercontrol에서 그린 화면으로 변경하고 싶습니다.

아래는 제 코드입니다.

<Page>
<Page.Resources>
    <DataTemplate x:Key="NavigationView_MainThemplate" x:DataType="vm:vmMenuItem">
        <Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="-15,5,-11,5">
            <Button VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
                    Background="Transparent" CornerRadius="0"
                    BorderBrush="Transparent" BorderThickness="0"
                    Command="{Binding DataContext.VMMain.NavigationCommand, ElementName=ListView_BottomNavigation}"
                    CommandParameter="{Binding Index}"
                    Style="{StaticResource AccentButtonStyle}">
                <StackPanel Orientation="Horizontal">
                    <Image Source="{Binding ImagePath}" Width="{Binding ImageWidth}"/>
                    <TextBlock Margin="20,0,0,0" Text="{Binding Name}" Foreground="White" FontSize="20" FontWeight="Bold" />
                </StackPanel>
            </Button>
        </Grid>
    </DataTemplate>
</Page.Resources>

<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    
    <SplitView x:Name="SplitView_Nav" 
               CompactPaneLength="50" 
               DisplayMode="CompactInline"
               IsPaneOpen="{Binding VMMain.IsPaneOpen, Mode=TwoWay}"
               OpenPaneLength="300"
               PaneBackground="{StaticResource Blue_0033BA}"
               PanePlacement="Left">
        <SplitView.Pane>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>

                    <Button Grid.Row="0" Width="50" Margin="0,5"
                            Background="Transparent" CornerRadius="0"
                            BorderThickness="0" BorderBrush="Transparent" 
                            VerticalAlignment="Stretch" HorizontalAlignment="Left" 
                            Style="{StaticResource AccentButtonStyle}"
                            Command="{Binding VMMain.NavigationSplitCommand}">
                        <StackPanel>
                            <FontIcon Glyph="&#xE700;" FontSize="25" Foreground="White" FontWeight="ExtraBold"/>
                        </StackPanel>
                    </Button>

                    <Button Grid.Row="1" 
                            Background="Transparent" CornerRadius="0" Margin="-5,0,0,0"
                            BorderThickness="0" BorderBrush="Transparent"
                            VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
                            Style="{StaticResource AccentButtonStyle}"
                            Command="{Binding }">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="{Binding MainLogo_Imgae}" Width="35" VerticalAlignment="Center"/>
                            <TextBlock Text="ONE LAB" Foreground="White" FontSize="30" FontWeight="ExtraBold"
                                       VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="20,0" />
                        </StackPanel>
                    </Button>
                </Grid>

                <Grid Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0,10">
                    <ScrollView>
                        <ListView x:Name="ListView_Navigation"
                                  ItemsSource="{Binding VMMain.MenuItemOb, Mode=OneWay}"
                                  ItemTemplate="{StaticResource NavigationView_MainThemplate}"
                                  SelectionMode="Single"
                                  SingleSelectionFollowsFocus="True">
                        </ListView>
                    </ScrollView>
                </Grid>

                <Grid Grid.Row="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
                    <ListView x:Name="ListView_BottomNavigation"
                              ItemsSource="{Binding VMMain.BottomMenuItemOb, Mode=OneWay}"
                              ItemTemplate="{StaticResource NavigationView_MainThemplate}"
                              SelectionMode="Single"
                              SingleSelectionFollowsFocus="True">
                    </ListView>
                </Grid>

            </Grid>
        </SplitView.Pane>
    </SplitView>
    
    <ScrollView Grid.Column="1">
        <Frame x:Name="mainFrame">
            <!--<uc:ucMain x:Name="UserControlMain" />-->
            <ContentControl Content="{Binding }"
        </Frame>
    </ScrollView>
</Grid>

이 부분은 Navigation을 그리기 위한 Model Class 부분입니다.

    public class vmMenuItem : ViewModelBase
    {

        public vmMenuItem() { }

        public vmMenuItem(int index, int row,string name, object content) 
        {
            Index = index;
            Row = row;
            Name = name;
            Content = content;
        }

#nullable enable
        public int Index { get; set; }
        
        public int Row {  get; set; }
        public string Name { get; set; }
        public string ToolTipMsg { get; set; }
        public Symbol? GlyphSymbol { get; set; }
        public string? ImagePath { get; set; }
        public double? ImageWidth { get; set; }
        public object Content { get; set; }
#nullable disable
    }

마지막으로 실제 화면이동을 담당할 Command가 있는 ViewModel입니다.

public vmMain()
{
    InitializationFirst();
    InitializationSecond();
    InitializationCommand();
}




#region Object
/// <summary>스크롤</summary>
public bool IsPaneOpen { get => GetValue<bool>(); set => SetValue(value); }
/// <summary></summary>

public ucMain Main_UserControl { get => GetValue<ucMain>(); set => SetValue(value); }
public ucHomeMain HomeMain_UserControl { get => GetValue<ucHomeMain>(); set => SetValue(value); }
public ObservableCollection<vmMenuItem> MenuItemOb { get => GetValue<ObservableCollection<vmMenuItem>>(); set => SetValue(value); }
public ObservableCollection<vmMenuItem> BottomMenuItemOb { get => GetValue<ObservableCollection<vmMenuItem>>(); set => SetValue(value); }
#endregion


#region Command
public DelegateCommand NavigationSplitCommand { get; set; }
public DelegateCommand NavigationSymbolLogoCommand { get; set; }

public AsyncCommand<int> NavigationCommand { get; set; }
async Task ExcuteNavigation(int index, CancellationToken cancellationToken)
{
    /*while (true)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            return;
        }
        await Task.Delay(20);
    }*/
    Main_UserControl = new ucMain();
    switch (index)
    {
        case 1:
            
            break;

        case 2:

            break;

        case 5: // Device

            break;

        case 6: // Info

            break;
    }
}
#endregion 



#region Method
public void InitializationFirst()
{
    MenuItemOb = new ObservableCollection<vmMenuItem>();
    BottomMenuItemOb = new ObservableCollection<vmMenuItem>();

    
    var menu1 = new vmMenuItem(1, 0, "Home", typeof(ucHomeMain))
    {
        ImagePath = "ms-appx:///Images/Common/home.png",
        ImageWidth = 30
    };
    var menu2 = new vmMenuItem(2, 0, "Manual", typeof(ucHomeMain))
    {
        ImagePath = "ms-appx:///Images/Common/manual.png",
        ImageWidth = 30
    };

    MenuItemOb.Add(menu1);
    MenuItemOb.Add(menu2);

    var menuBottom1 = new vmMenuItem(5, 0, "Device Setting", typeof(ucHomeMain))
    {
        ImagePath = "ms-appx:///Images/Common/device_setting.png",
        ImageWidth = 25
    };
    var menuBottom2 = new vmMenuItem(6, 0, "INFO", typeof(ucHomeMain))
    {
        ImagePath = "ms-appx:///Images/Common/info.png",
        ImageWidth = 25
    };
    BottomMenuItemOb.Add(menuBottom1);
    BottomMenuItemOb.Add(menuBottom2);

    
}
public void InitializationSecond()
{
    IsPaneOpen = true;
}


public void InitializationCommand()
{
    NavigationCommand = new AsyncCommand<int>(ExcuteNavigation);
    NavigationSymbolLogoCommand = new DelegateCommand(execute: () => NavigationCommand.Execute(1));
    NavigationSplitCommand = new DelegateCommand(execute: () =>
    {
        if (IsPaneOpen) IsPaneOpen = false;
        else IsPaneOpen = true;
    });
}

ExcuteNavigation 안에 화면이동을 하기 위한 코드를 작성하려 하는데 이 부분에서 막혀서요… 도움의 손길을 주신다면 감사하겠습니다 ㅜㅜ