我的 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 仍然比魔术字符串更好。而且我可以自动测试(通过反射)所有调用是否有效。
最佳答案
您不需要 WPF 中的所有 ScreenManager 东西,因为 DataTemplate 引擎可以使用纯标记为您处理这些事情。
您可以使用 ContentPresenter 和一组 DataTemplates 简单地对应用程序的特定区域进行数据绑定(bind)。将该区域绑定(bind)到“根”ViewModel 的属性,并让“根”ViewModel 实现 INotifyPropertyChanged,以便 WPF 知道您是否更改了该区域中的 ViewModel。
public class RootViewModel : INotifyPropertyChanged
{
public object Screen1ViewModel { get; }
public object Screen2ViewModel { get; }
}
使用数据绑定(bind)一个 ContentPresenter 控件到 Screen1ViewModel 属性
<ContentControl Content="{Binding Path=Screen1ViewModel}" />
下一个也是如此。当您需要更改 Screen1 的内容时,您只需从代码中重新分配 Screen1ViewModel,并且由于引发的 PropertyChanged 事件,WPF 将选取它并将新的 ViewModel 绑定(bind)到新的 View 。
DataTemplates 可能像这样简单:
<Window.Resources>
<DataTemplate DataType="{x:Type foo:MyViewModel}">
<self:MyControl />
</DataTemplate>
<DataTemplate DataType="{x:Type foo:MyOtherViewModel}">
<self:MyOtherControl />
</DataTemplate>
</Window.Resources>
如果您不熟悉它,this article on MVVM in WPF是一个很好的介绍。
关于c# - 无需魔术弦即可分离屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2239932/