C# 如何最好地应用WPF MVVM?
我正在尝试设置一个MVVM风格的应用程序,我想我对这些项目的交互感到有些困惑,希望有人能帮助我。我真的做错什么了吗 我想我的两个主要问题是C# 如何最好地应用WPF MVVM?,c#,.net,wpf,mvvm,C#,.net,Wpf,Mvvm,我正在尝试设置一个MVVM风格的应用程序,我想我对这些项目的交互感到有些困惑,希望有人能帮助我。我真的做错什么了吗 我想我的两个主要问题是 我应该如何从我的模型到我的观点。目前我正试图通过转换器来实现这一点 如果使用转换器是正确的,如何使其正常工作?我相信节点构造函数上的datacontext集已被包含转换器的XAML所取代 我的课程(简化了一点): IFieldDescription // Interface that is supposed to be the Model public
// Interface that is supposed to be the Model
public interface IFieldDescription
{
String Name { get; }
bool Disabled { get; }
}
节点模型
// Class that is supposed to be the ViewModel
public class NodeModel : NotifyPropertyChanged
{
internal NodeModel() { }
public NodeModel(IFieldDescription fieldDescription)
{
this.FieldDescription = fieldDescription;
}
protected IFieldDescription FieldDescription
{
get { return this.fieldDescription; }
set {
this.fieldDescription = value;
this.OnPropertyChanged("Name");
this.OnPropertyChanged("Disabled");
this.OnPropertyChanged("PrimaryKey"); }
}
private IFieldDescription fieldDescription;
public String Name { get { return this.FieldDescription.Name; } }
public Boolean Disabled { get { return this.FieldDescription.Disabled; } }
}
节点
代码隐藏
public Node(NodeModel model)
{
this.DataContext = model;
this.InitializeComponent();
}
XAML
通常我使用
数据模板
将视图
与模型
或视图模型
当我的视图将启动视图模型设置为启动视图的DataContext
时,唯一将我的视图代码放在模型或视图模型引用后面的地方是在启动时。其他所有内容都与数据模板
(或Silverlight的数据模板选择器
连接)
(事实上,为了公平起见,有时我确实需要做一些特殊的事情,我会将对象的DataContext
转换为ViewModel或代码背后的模型,但这些情况很少见,我将它们视为黑客)
例如,设置启动视图/视图模型:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var app = new ShellView();
var context = new ShellViewModel();
app.DataContext = context;
app.Show();
}
}
以下是一些数据模板的示例:
<Window.Resources>
<DataTemplate DataType="{x:Type local:SomeViewModel}">
<local:SomeViewForViewModel />
</DataTemplate>
<DataTemplate DataType="{x:Type local:SomeModel}">
<local:SomeViewForModel />
</DataTemplate>
</Window.Resources>
或
MVVM背后的思想是,整个应用程序都在ViewModels中运行,而视图只是一个漂亮的UI,它位于ViewModels之上,使它们更加用户友好。在一个完美的世界中,视图可以很容易地被任何其他UI替换
如果您感兴趣,我在我的博客上有一篇文章,其中包含一些使用MVVM设计模式的示例。通常,我使用
数据模板
将视图
与模型
或视图模型
当我的视图将启动视图模型设置为启动视图的DataContext
时,唯一将我的视图代码放在模型或视图模型引用后面的地方是在启动时。其他所有内容都与数据模板
(或Silverlight的数据模板选择器
连接)
(事实上,为了公平起见,有时我确实需要做一些特殊的事情,我会将对象的DataContext
转换为ViewModel或代码背后的模型,但这些情况很少见,我将它们视为黑客)
例如,设置启动视图/视图模型:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var app = new ShellView();
var context = new ShellViewModel();
app.DataContext = context;
app.Show();
}
}
以下是一些数据模板的示例:
<Window.Resources>
<DataTemplate DataType="{x:Type local:SomeViewModel}">
<local:SomeViewForViewModel />
</DataTemplate>
<DataTemplate DataType="{x:Type local:SomeModel}">
<local:SomeViewForModel />
</DataTemplate>
</Window.Resources>
或
MVVM背后的思想是,整个应用程序都在ViewModels中运行,而视图只是一个漂亮的UI,它位于ViewModels之上,使它们更加用户友好。在一个完美的世界中,视图可以很容易地被任何其他UI替换
如果您感兴趣,我在我的博客上有一篇文章,其中包含一些使用MVVM设计模式的示例请不要在控件的构造函数中将
this.DataContext
设置为smth。用这种方法你会击中自己的腿<控件的code>DataContext只能从外部设置,通常从其父级设置。在构造函数中设置了this.DataContext=…
,总有一天你会遇到一场噩梦,试图理解“为什么我的绑定在这个控件上不起作用”@Snowbear:谢谢你的评论,建议指出。我仍在努力了解WPF的基本知识,很高兴承认我可能犯了一些错误。请永远不要在控件的构造函数中将this.DataContext
设置为smth。用这种方法你会击中自己的腿<控件的code>DataContext只能从外部设置,通常从其父级设置。在构造函数中设置了this.DataContext=…
,总有一天你会遇到一场噩梦,试图理解“为什么我的绑定在这个控件上不起作用”@Snowbear:谢谢你的评论,建议指出。我仍在努力了解WPF的基本知识,很高兴承认我可能犯了一些错误。
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var app = new ShellView();
var context = new ShellViewModel();
app.DataContext = context;
app.Show();
}
}
<Window.Resources>
<DataTemplate DataType="{x:Type local:SomeViewModel}">
<local:SomeViewForViewModel />
</DataTemplate>
<DataTemplate DataType="{x:Type local:SomeModel}">
<local:SomeViewForModel />
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding SomeViewModelProperty}" />
<ContentControl Content="{Binding SomeModelProperty}" />
<ListView ItemsSource="{Binding Path=CollectionOfNodeModel}">
<ListView.Resources> <!-- Could also put this in Window.Resources -->
<DataTemplate DataType="{x:Type local:NodeModel}">
<local:Node /> <!-- DataContext will implicitly be the NodeModel object -->
</DataTemplate>
</ListView.Resources>
</ListView>