无需魔术弦即可解耦屏幕
我的 WPF 项目将这样组织:
Screens
Group1
Screen1
View.xaml
ViewModel.cs
Group2
Screen2
View.xaml
ViewModel.cs
要从 Screen2
显示 Screen1
,我将使用如下内容:ScreenManager.Show("Group1.Screen1" )
这会在 Screens.Group1.Screen1
命名空间中查找(使用反射)View 和 ViewModel 并实例化它们。
如何在不耦合 Screen1
和 Screen2
的情况下消除魔术字符串(我不希望 Screen2
中的类使用 Screen1
命名空间)。另外我想要某种屏幕发现(自动完成/智能感知)
或者某种方式(自动测试)来验证对 ScreenManager.Show 的所有调用是否有效。
更新: 我想出了这个:
public class ScreenNames
{
public Group1Screens Group1;
public class Group1Screens
{
public ScreenName Screen1;
}
}
public sealed class ScreenName
{
private ScreenName() { }
}
public class ScreenManager : IScreenManager
{
public void Show(Expression<Func<ScreenNames, ScreenName>> x) {}
}
用法:
screenManager.Show(x=>x.Group1.Screen1);
不理想,但我认为违反 DRY 仍然比魔术字符串更好。我可以自动测试(通过反射)所有调用是否有效。
My WPF project will be organised like this :
Screens
Group1
Screen1
View.xaml
ViewModel.cs
Group2
Screen2
View.xaml
ViewModel.cs
To show the Screen1
from the Screen2
I'll use something like this: ScreenManager.Show("Group1.Screen1")
This looks (using reflection) in the Screens.Group1.Screen1
namespace for a View and a ViewModel and instantiates them.
How can I eliminate the magic string without coupling Screen1
and Screen2
(I don't want the classes in Screen2
to use the Screen1
namespace). Also I would like some kind of screen discovery (autocompletion/intellisense)
Or maybe some way (automate test) to verify that all calls to ScreenManager.Show
are valid.
Update :
I came up with this:
public class ScreenNames
{
public Group1Screens Group1;
public class Group1Screens
{
public ScreenName Screen1;
}
}
public sealed class ScreenName
{
private ScreenName() { }
}
public class ScreenManager : IScreenManager
{
public void Show(Expression<Func<ScreenNames, ScreenName>> x) {}
}
Usage:
screenManager.Show(x=>x.Group1.Screen1);
Not ideal but I suppose violating DRY is still better than magic strings. And I can automatically test (with reflection) that all calls are valid.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您不需要 WPF 中的所有 ScreenManager 内容,因为 DataTemplate 引擎可以通过纯标记为您处理这些事情。
您可以简单地使用 ContentPresenter 和一堆 DataTemplates 对应用程序的特定区域进行数据绑定。将该区域绑定到“根”ViewModel 的属性,并让“根”ViewModel 实现 INotifyPropertyChanged,以便 WPF 知道您是否更改了该区域中的 ViewModel。
将一个 ContentPresenter 控件数据绑定到 Screen1ViewModel 属性
使用和 类似方法 。当您需要更改 Screen1 的内容时,只需从代码中重新分配 Screen1ViewModel ,并且由于引发了 PropertyChanged 事件,WPF 将拾取它并将新的 ViewModel 绑定到新的 View。
DataTemplates 可能像这样简单:
如果您不熟悉它,这篇关于 WPF 中的 MVVM 的文章是一个很好的介绍。
You don't need all that ScreenManager stuff in WPF, because the DataTemplate engine can take care of this for you with pure markup.
You can simply databind a particular area of your application with a ContentPresenter and a bunch of DataTemplates. Bind the area to a property of a 'root' ViewModel, and let the 'root' ViewModel implement INotifyPropertyChanged so that WPF knows if you change the ViewModel in that area.
Databind one ContentPresenter control to the Screen1ViewModel property using
and similarly for the next one. When you need to change the content of Screen1, you simply re-assign Screen1ViewModel from code, and because of the raised PropertyChanged event, WPF will pick it up and bind the new ViewModel to a new View.
The DataTemplates may be as simple as this:
In case you are not familiar with it, this article on MVVM in WPF is an excellent introduction.
最后,我使用 T4 代码生成来生成我的
ScreenNames
类。我通过调整以下代码来做到这一点: 自动生成强类型ASP.NET Web 应用程序中所有用户控件的导航类Finally I used T4 code generation to generate my
ScreenNames
class. I did that by adapting this code : Auto generate strong typed navigation class for all user controls in ASP.NET web application