如何在不创建 ViewModel 对象的情况下指定 DataContext (ViewModel) 类型以在 XAML 编辑器中进行设计时绑定检查?
How do I specify DataContext (ViewModel) type to get design-time binding checking in XAML editor without creating a ViewModel object?
我可以这样指定 DataContext:
<Window ... >
<Window.DataContext>
<MainViewModel />
</Window.DataContext>
...
</Window>
在这种情况下,WPF 将创建一个 MainViewModel 类型的对象并将其分配给 window 的 DataContext 属性(这发生在 Window 的 InitializeComponent()
方法)。
但是如果我的 ViewModel
没有默认构造函数怎么办。或者,如果我想在 Window.InitializeComponent()
执行后初始化 ViewModel 并将其分配给 DataContext(在 Window 的构造函数内或从实例化 window 的相同代码)怎么办 - 在本例中为 WPF创建一个 ViewModel(在 InitializeComponent()
内),将其分配给 window 的 DataContext,然后我用另一个 ViewModel 实例覆盖它(我担心这里不必要的对象实例化)。
我希望能够指定 ViewModel
的一种类型,因此如果我在 {Binding} 中拼错 属性 名称(或在重命名属性),或者我可以通过单击(在 XAML 中){Binding PropertyName}
.
中的 属性 名称来进行声明
如果您自己动手做 MVVM,那将是棘手的部分。
你的选择,基本上:
使用依赖注入
您可以在 Page
/Window
的构造函数中注入 ViewModel 并在其中分配它。
虽然这有一些缺点。
- 更难使用设计时视图模型
- 无法再从 XAML 实例化视图
首先使用导航服务的 ViewModel
您将解析您的 ViewModel 并通过导航服务进行所有导航。在您的 ViewModel 中,您传递了 INavigationService
。您可以使用 ViewModel 类型导航到视图。在它内部通过依赖注入实例化 ViewModel,然后实例化视图(基于命名约定或通过 DI 配置)
好一点,但仍然不允许您在 XAML 中实例化视图。最大的优点是,它允许您轻松地将参数传递给 ViewModel(让 ViewModels 使用 NavigatedTo
方法实现 INavigationAware
属性,在实例化并将参数传递给之后调用)
ViewModelLocator/附上Property/Behavior
有了这个,您将创建一个附加的 属性,您可以将其设置为 true
(即自动装配)或 ViewModel 类型(以更好地控制实例化的 ViewModel)和查找并解析 ViewModel 并分配它。
它基本上提供了上述所有优点以及实例化形式的视图。
最后一个基本上是 Microsoft 的 MVVM 框架 "Prism" 所做的(导航服务 navigationService.Navigate("MyPage", myParameterForViewModel)
,通过自动装配从 XAML 进行 DataContext 实例化和分配(在 XAML 中:prism:ViewModelLocator.AutoWireViewModel="True"
).
也就是说,最好使用成熟的 MVVM 框架来完成这部分布线(即使您决定不使用基础 类,例如 BindableBase
或任何所谓的在所述框架内)。
关于 ViewModel 的设计时 ViewModel/auto-completition:
您可以使用 Blend 的设计时属性来执行此操作。您需要先添加 Blend 程序集引用。然后你可以将 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
命名空间添加到你的 page/view 中。
然后您可以通过d:DataContext="{d:DesignInstance my:DesignTimeViewModel, IsDesignTimeCreatable=True}
将其绑定到您的页面。注意 DataContext 之前的 d:
,这很重要。此 DataContext 将仅在 Designer 中使用(Visual Studio XAML Designer 或在 Blend 中)。这是为了防止干扰正常的 DataContext
(没有前缀)。
示例:
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:myApp="clr-namespace:WpfApplication1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance myApp:Window2ViewModel, IsDesignTimeCreatable=True}">
<Grid>
<TextBlock Text ="{Binding Test}"/>
</Grid>
</Window>
如果您为 ViewModel 使用接口,创建设计实例会非常快,只需让 Visual Studio 实现所有接口 属性 并给它一些默认值(对于 属性 所以你的 ViewModel 中有示例数据来验证绑定是否正常工作)。
这需要您创建单独的设计时 ViewModel 和您的实际 ViewModel,这并不像听起来那么糟糕。这使您的 UI 设计师有机会使用它,即使真正的 ViewModel 还不是 finished/implemented。
我可以这样指定 DataContext:
<Window ... >
<Window.DataContext>
<MainViewModel />
</Window.DataContext>
...
</Window>
在这种情况下,WPF 将创建一个 MainViewModel 类型的对象并将其分配给 window 的 DataContext 属性(这发生在 Window 的 InitializeComponent()
方法)。
但是如果我的 ViewModel
没有默认构造函数怎么办。或者,如果我想在 Window.InitializeComponent()
执行后初始化 ViewModel 并将其分配给 DataContext(在 Window 的构造函数内或从实例化 window 的相同代码)怎么办 - 在本例中为 WPF创建一个 ViewModel(在 InitializeComponent()
内),将其分配给 window 的 DataContext,然后我用另一个 ViewModel 实例覆盖它(我担心这里不必要的对象实例化)。
我希望能够指定 ViewModel
的一种类型,因此如果我在 {Binding} 中拼错 属性 名称(或在重命名属性),或者我可以通过单击(在 XAML 中){Binding PropertyName}
.
如果您自己动手做 MVVM,那将是棘手的部分。
你的选择,基本上:
使用依赖注入
您可以在 Page
/Window
的构造函数中注入 ViewModel 并在其中分配它。
虽然这有一些缺点。
- 更难使用设计时视图模型
- 无法再从 XAML 实例化视图
首先使用导航服务的 ViewModel
您将解析您的 ViewModel 并通过导航服务进行所有导航。在您的 ViewModel 中,您传递了 INavigationService
。您可以使用 ViewModel 类型导航到视图。在它内部通过依赖注入实例化 ViewModel,然后实例化视图(基于命名约定或通过 DI 配置)
好一点,但仍然不允许您在 XAML 中实例化视图。最大的优点是,它允许您轻松地将参数传递给 ViewModel(让 ViewModels 使用 NavigatedTo
方法实现 INavigationAware
属性,在实例化并将参数传递给之后调用)
ViewModelLocator/附上Property/Behavior
有了这个,您将创建一个附加的 属性,您可以将其设置为 true
(即自动装配)或 ViewModel 类型(以更好地控制实例化的 ViewModel)和查找并解析 ViewModel 并分配它。
它基本上提供了上述所有优点以及实例化形式的视图。
最后一个基本上是 Microsoft 的 MVVM 框架 "Prism" 所做的(导航服务 navigationService.Navigate("MyPage", myParameterForViewModel)
,通过自动装配从 XAML 进行 DataContext 实例化和分配(在 XAML 中:prism:ViewModelLocator.AutoWireViewModel="True"
).
也就是说,最好使用成熟的 MVVM 框架来完成这部分布线(即使您决定不使用基础 类,例如 BindableBase
或任何所谓的在所述框架内)。
关于 ViewModel 的设计时 ViewModel/auto-completition:
您可以使用 Blend 的设计时属性来执行此操作。您需要先添加 Blend 程序集引用。然后你可以将 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
命名空间添加到你的 page/view 中。
然后您可以通过d:DataContext="{d:DesignInstance my:DesignTimeViewModel, IsDesignTimeCreatable=True}
将其绑定到您的页面。注意 DataContext 之前的 d:
,这很重要。此 DataContext 将仅在 Designer 中使用(Visual Studio XAML Designer 或在 Blend 中)。这是为了防止干扰正常的 DataContext
(没有前缀)。
示例:
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:myApp="clr-namespace:WpfApplication1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance myApp:Window2ViewModel, IsDesignTimeCreatable=True}">
<Grid>
<TextBlock Text ="{Binding Test}"/>
</Grid>
</Window>
如果您为 ViewModel 使用接口,创建设计实例会非常快,只需让 Visual Studio 实现所有接口 属性 并给它一些默认值(对于 属性 所以你的 ViewModel 中有示例数据来验证绑定是否正常工作)。
这需要您创建单独的设计时 ViewModel 和您的实际 ViewModel,这并不像听起来那么糟糕。这使您的 UI 设计师有机会使用它,即使真正的 ViewModel 还不是 finished/implemented。