在视图和视图模型之间切换

4
有没有办法让Resharper或者“只是”Visual Studio(也许使用宏)在MVVM模式中在视图和其视图模型之间跳转呢?
就像Resharper可以使用F7和Shift-F7在xaml和其代码后台之间跳转一样。
我遵循文件按如下方式定位的约定
\Views\name\AbcView.xaml \ViewModels\name\AbcViewModel.xaml

据我所知,F7和Shift-F7是来自VisualStudio而不是ReSharper的关键手势。 - WaltiD
我不是很确定,但我喜欢使用“最近文件”视图(对我来说,开箱即用的映射是Ctrl-,)。 - Random Dev
3个回答

2
也许我应该先谷歌一下,这里有一个宏可以对.cpp和.h文件做同样的事情。我稍微修改了一下并将宏分配给了Ctrl+F7键。看起来工作得很好。
Public Sub SwitchBetweenViewAndViewModel()
    '=====================================================================  
    ' If the currently open document is a view or viewmodel, attempts to  
    ' switch between them
    '=====================================================================  
    Dim currentDocument As String
    Dim targetDocument As String

    currentDocument = ActiveDocument.FullName

    If currentDocument.ToLower().Contains("\views\") And _
       (currentDocument.EndsWith("View.xaml", StringComparison.InvariantCultureIgnoreCase) Or _
        currentDocument.EndsWith("View.xaml.cs", StringComparison.InvariantCultureIgnoreCase)) Then
        targetDocument = currentDocument
        targetDocument = targetDocument.Replace(".xaml.cs", "")
        targetDocument = targetDocument.Replace(".xaml", "")
        targetDocument = targetDocument.Replace("\Views\", "\ViewModels\")
        targetDocument = targetDocument + "Model.cs"
    ElseIf currentDocument.ToLower().Contains("\viewmodels\") And currentDocument.EndsWith(".cs", StringComparison.InvariantCultureIgnoreCase) Then
        targetDocument = currentDocument
        targetDocument = targetDocument.Replace("\ViewModels\", "\Views\")
        targetDocument = targetDocument.Replace("ViewModel.cs", "View.xaml")
    End If

    If System.IO.File.Exists(targetDocument) Then
        OpenDocument(targetDocument)
    End If
End Sub

'=====================================================================  
' Given a document name, attempts to activate it if it is already open,  
' otherwise attempts to open it.  
'=====================================================================  
Private Sub OpenDocument(ByRef documentName As String)
    Dim document As EnvDTE.Document
    Dim activatedTarget As Boolean
    activatedTarget = False

    For Each document In Application.Documents
        If document.FullName = documentName And document.Windows.Count > 0 Then
            document.Activate()
            activatedTarget = True
            Exit For
        End If
    Next
    If Not activatedTarget Then
        Application.Documents.Open(documentName, "Text")
    End If
End Sub

对于 Visual Studio 2012,宏默认不可用。这里有一个扩展程序:https://blogs.msdn.microsoft.com/visualstudio/2016/05/11/macros-extension-open-sourced-in-visual-studio-2015/ - Stefan

1

如果一个视图与多个ViewModel相关联怎么办? :)

您可以简单地使用DesignInstance标记扩展来获得R#导航和代码完成在绑定工作中良好:

namespace WpfApplication1.ViewModels
{
  public class PersonViewModel
  {
    public string Name { get; set; }
    public int Age     { get; set; }
  }
}

以及相应的视图:

<Window x:Class="WpfApplication1.Views.PersonView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="PersonInfo" Height="300" Width="300"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        mc:Ignorable="d"

        xmlns:vms="clr-namespace:WpfApplication1.ViewModels"

        d:DataContext="{d:DesignInstance Type=vms:PersonViewModel}">

  <UniformGrid>
    <TextBlock Grid.Row="0" Grid.Column="0" Text="Name" />
    <TextBlock Grid.Row="0" Grid.Column="1" Text="Age" />
    <TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding Name}" />
    <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Age}" />
  </UniformGrid>

</Window>

现在R#可以验证绑定中ViewModel属性的所有引用,帮助您完成属性名称,并且还可以直接导航到这些属性。此外,上面的所有代码都可以使用R#Specify DataContext type in ...快速修复(在未解决的绑定表达式中)快速生成。

p.s. View仍然不依赖于ViewModel,因为所有设计时属性将在编译后被删除(通过mc:Ignorable="d"属性)。


{d:DesignerInstance}/{d:DesignData} 只支持 R# 6.0,但早期版本可以在其他情况下推断 DataContext 类型,例如绑定到资源或通过 ElementName 绑定到其他元素。 - controlflow

1

借鉴@Karstens的答案,我修改了在文件之间切换的子程序,使其能够在.cpp和.h文件以及View和View Model文件之间进行切换。

如果您想要做同样的事情,请按照他链接中的说明,但使用这个子程序:

'=====================================================================  
' If the currently open document is a CPP or an H file, attempts to  
' switch between the CPP and the H file.  
'
' If the currently open document is a View.xml or an ViewModel.cs file, attempts to  
' switch between the View and the ViewModel file.  
'=====================================================================  
Sub SwitchBetweenAssociatedFiles()
    Dim currentDocument As String
    Dim targetDocument As String

    currentDocument = ActiveDocument.FullName

    If currentDocument.EndsWith(".cpp", StringComparison.InvariantCultureIgnoreCase) Then
        targetDocument = Left(currentDocument, Len(currentDocument) - 3) + "h"
    ElseIf currentDocument.EndsWith(".h", StringComparison.InvariantCultureIgnoreCase) Then
        targetDocument = Left(currentDocument, Len(currentDocument) - 1) + "cpp"
    ElseIf currentDocument.EndsWith("View.xaml", StringComparison.InvariantCultureIgnoreCase) Then
        targetDocument = currentDocument.Replace("\Views\", "\ViewModels\")
        targetDocument = targetDocument.Replace("\View\", "\ViewModel\")
        targetDocument = targetDocument.Replace("View.xaml", "ViewModel.cs")
    ElseIf currentDocument.EndsWith("ViewModel.cs", StringComparison.InvariantCultureIgnoreCase) Then
        targetDocument = currentDocument.Replace("\ViewModels\", "\Views\")
        targetDocument = targetDocument.Replace("\ViewModel\", "\View\")
        targetDocument = targetDocument.Replace("ViewModel.cs", "View.xaml")
    End If

    If System.IO.File.Exists(targetDocument) Then
        OpenDocument(targetDocument)
    End If

End Sub

我将它分配给了Alt + §,这在我的配置中是空闲的。方便与Alt + Tab并用。^_^


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接