我通常像这样进行绑定 - Command="{Binding SomeCommand}",其中 SomeCommand 是来自 DataContext 的命令。
但在这个教育项目https://github.com/xellans/LearnMvvm.git中,我遇到了一个对我来说不寻常的选项
<RadioButton Command="{local:SetCurrentContext}" CommandParameter="PersonVM" Content="{DynamicResource Lang1}"></RadioButton>
这是绑定命令的可接受的方式吗?哪种方法被认为更正确?
为了使此绑定起作用,您的命令(以及要绑定的任何其他对象)必须是静态的,打开代码,查看,确实:
嗯,静态是邪恶的,因为至少
我并不是说你不应该有静态,我是说如果有这样的机会,最好不要有静态,在这种特殊情况下,有这样的机会。
现在考虑一下如何实现其他命令来绑定视图
{local:SetCurrentContext}?产生大量静态对象?我想你自己也明白这是一个愚蠢的决定。因此,对于单次使用,如定位器的示例(我们稍后会讨论),这种方法可能是有意义的,但是将所有属性设置为静态绑定就是搬起石头砸自己的脚。如果您更详细地研究示例中的代码,您将看到更多的普通命令和普通绑定,例如,
AuthUserControl.xaml它包含Command="{Binding AuthorizeCommand}",并且在 VM 中已经有一个标准的非静态属性public RelayCommand AuthorizeCommand { get; }。现在,至于定位器
,老实说,我不喜欢这种方法,原因如下:
App.xaml.cs->(NavigatorLocator)this.FindResource("locator");)。当您有一个非常大的项目时,定位器是很好的选择,但这不是事实,因为如上面的示例所示,该项目使用 IoC 容器,通过它我们可以轻松请求我们需要的一切。因此,我个人不会使用这样的定位器,但是否值得由您决定。
现在我将向您展示为什么我认为“定位器”是多余的。
让我们以我们的项目将使用 IoC 容器为基础(在建议的示例中,这是
InstancesProvider,在我的例子中它将是库)Microsoft.Extensions.DependencyInjection。创建一个新项目
打开
App.xaml和收起StartupUri="MainWindow.xaml"让我们为我们的窗口创建一个类,让它成为标准的
MainViewModel我们打开
App.xaml.cs并重新定义那里OnStartup,在其中指定容器的初始化,从中获取窗口和VM,然后打开窗口,我们得到如下内容:这是一个“笨拙”的实现,有充分的理由应该有一个单独的服务负责“映射”,我们在这里询问并通过它打开,但为了举例(且不仅仅是),我认为它可以。
让我们运行该项目并看到一个空窗口。恭喜,我们已经创建了一个带有 IoC 容器的项目。
现在让我们考虑内容(页面),让一个单独的服务负责它们,这将通知侦听器页面已更改。
我们创建一个接口,作为VM页面层的“联系人”,让它简单而空
interface IPage。现在让我们创建另一个接口来描述服务本身,或者更确切地说什么是“公共”,即更改内容的方法,甚至是一个事件,如下所示:
现在让我们尽可能简单地实现服务本身,如下所示:
在容器中注册服务
.AddSingleton<IContentService, ContentService>()现在我们来实现
MainViewModel不用管
ObservableObject这个ObservableProperty,你可以在这里进行任何实现INotifyPropertyChanged。就我而言,它被使用CommunityToolkit.MVVM。让我们用 XAML 编写窗口
<ContentPresenter Content="{Binding CurrentPage}" />;这对于示例来说就足够了。现在我想你可以看到我们的代码是多么简单;我们创建了一个没有任何资源、静态对象的服务,并实现了它,现在我们可以在任何地方使用它。现在看一下该定位器并回答“为什么?”的问题......我个人无法回答)
我认为编写进一步的示例是没有意义的(如果您需要它,请告诉我,我会添加它),但一般来说,我们只需为必要的页面创建一个虚拟机,然后继承它们
IPage并将每个页面注册到容器中,并且IContentService如果我们需要更改页面,也可以在所需的 VM 中(不仅如此)实现它,因此我们调用Change()具有所需 VM 类型的页面的方法来打开 (contentService.Change<LoginVM>();)。实际上,这些是我对此事的想法,我想我已经清楚地解释了为什么我不喜欢这样的绑定,以及为什么我不太喜欢定位器,尤其是当我手头有一个 IoC 容器时......