这段代码是否破坏了MVVM?

时间:2016-01-15 10:13:33

标签: wpf vb.net mvvm

使用MVVM构建我的第一个项目,我想知道以下代码是否破坏了模型。

该命令的目的是在两个UserControls(ucDrumStandard和ucDrumStandardList)之间切换。两者共享相同的viewmodel。 此视图模型继承自包含" ParentContext"的viewmodelbase。 用户控件已存储'在ParentContext.listOfViews中。

(为我的VB代码道歉; - )

#Region "CmdSwitchDrumStandardView"

Public ReadOnly Property CmdSwitchDrumStandardView() As ICommand
    Get
        If _cmdSwitchDrumStandardView Is Nothing Then
            _cmdSwitchDrumStandardView = New RelayCommand(AddressOf SwitchDrumStandardView)

        End If
        Return _cmdSwitchDrumStandardView
    End Get
End Property

Private Sub SwitchDrumStandardView()

    ' There are  two views(ucDrumStandard and ucDrumStandardList) for the same viewmodel 

    If ParentContext.CurrentView.Uid = "ucDrumStandard" Then

        ' switch to ucDrumStandardGrid

        If ParentContext.ListOfViews.ContainsKey("ucDrumStandardGrid") Then

            ParentContext.CurrentView = (From obj As KeyValuePair(Of String, UIElement) In ParentContext.ListOfViews
                                    Where obj.Key = "ucDrumStandardGrid"
                                    Select obj.Value).FirstOrDefault
        Else

            Dim m_ucDrumStandardGrid = New ucDrumStandardGrid


            ParentContext.ListOfViews.Add("ucDrumStandardGrid", m_ucDrumStandardGrid)
            ParentContext.CurrentView = m_ucDrumStandardGrid

        End If

    ElseIf ParentContext.CurrentView.Uid = "ucDrumStandardGrid" Then

        ' switch to ucDrumStandard

        If ParentContext.ListOfViews.ContainsKey("ucDrumStandard") Then

            ParentContext.CurrentView = (From obj As KeyValuePair(Of String, UIElement) In ParentContext.ListOfViews
                                    Where obj.Key = "ucDrumStandard"
                                    Select obj.Value).FirstOrDefault
        Else

            Dim m_ucDrumStandard = New ucDrumStandard

            ParentContext.ListOfViews.Add("ucDrumStandard", m_ucDrumStandard)
            ParentContext.CurrentView = m_ucDrumStandard

        End If

    End If

End Sub

#End Region

1 个答案:

答案 0 :(得分:3)

在MVVM模式中,ViewModel& amp;视图图层只能通过Binding& amp;命令。 ViewModel代码不应该使用FrameworkElements所以是的,你的代码“打破”MVVM模式。

我假设您的ParentContext是一个ViewModel类,它应该具有一个CurrentView属性,该属性属于“Page”对象的ViewModel层的类型。

View层中ViewModel对象的渲染应该使用DataTemplate& amp;绑定。我将添加一个说明这一切的小样本。

//视图模型

public class AppVM : INotifyPropertyChanged {

    //your code...

    private PageVM _currentView;
    public PageVM CurrentView {
        get {return _currentView;}
        set {
            _currentView = value;
            OnPropertyChanged("CurrentView");
        }
    }
}

public class PageVM : INotifyPropertyChanged {
    //your "view" data visible in the UI
}

// XAML

<ContentControl Content="{Binding CurrentView, Mode=OneWay}">
    <ContentControl.Resources>
        <DataTemplate DataType="{x:Type ucDrumStandardVM}">
            <ucDrumStandard/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type ucDrumStandardListVM}">
            <ucDrumStandardList/>
        </DataTemplate>
    </ContentControl.Resources>
</ContentControl>

如果你真的想为两个“页面”保留相同的ViewModel对象,那么你必须使用一个触发器

<ContentControl Content="{Binding CurrentView, Mode=OneWay}">
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding CurrentView.Uid, Mode=OneWay}" Value="ucDrumStandard">
                    <Setter Property="ContentTemplate">
                        <DataTemplate>
                            <ucDrumStandard/>
                        </DataTemplate>
                    </Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding CurrentView.Uid, Mode=OneWay}" Value="ucDrumStandardGrid">
                    <Setter Property="ContentTemplate">
                        <DataTemplate>
                            <ucDrumStandardList/>
                        </DataTemplate>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Resources>
</ContentControl>