在本文中,将介绍如何使用Windows Presentation Foundation (WPF) 创建一个简单的音乐应用界面,该界面将展示艺术家及其相关的专辑和曲目。虽然这个界面非常基础,但它足以展示将要使用的工具,后续的文章将使用WPF的强大功能来美化和转换屏幕,使其更加美观。
首先,需要添加一个WPF项目。将项目命名为MusicApp.WPF.Client。如果更改了MainWindow.xaml文件的名称,不要忘记在app.xaml中更改启动URI。
在项目结构方面,为视图、视图模型和公共文件设置了单独的文件夹。
一旦基本结构就位,就可以向Views文件夹添加视图。在这种情况下,视图是一个用户控件,将把它添加到主窗口中。
视图本身非常简单——一个包含3个ListBox的网格,创建如下:
这是一个2x2网格的视图,列宽相等(每个占网格的1/2),第一行占70%的宽度,第二行占30%。网格内有一个ListBox占据了整个顶部行(ColumnSpan=2),以及在底部行的每列中各有一个ListBox。
已经包含了所有的绑定,这样当编写视图模型时就知道需要什么了。将需要一个名为‘Artists’的集合属性,以及两个属性用于选择艺术家和选择专辑。
DisplayMemberPath详细说明了对象的哪个属性将作为ListBoxItem中的文本显示。
一旦控件编写完成,就可以将其添加到主窗口XAML中。要将一个usercontrol添加到另一个XAML文件中,需要做两件事:
添加正确的namespace和添加控件。添加namespace需要在主窗口文件的顶部添加一个xmlns:
xmlns:views="clr-namespace:MusicApp.WPF.Client.Views"
一旦有了这个,就可以简单地将控件作为窗口上的一个新对象添加:
这给一个主窗口,其XAML如下:
现在视图已经完成,可以创建一个视图模型来支持它。视图模型将需要实现INotifyPropertyChanged,并且有以下片段方法来触发它实现的事件:
private void Notify(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
想在这里能够使用不同的数据提供者,所以将在这一点上将Unity IoC容器引入应用程序。Unity可以直接从NuGet安装到当前项目(install-package unity)或者可以直接下载。在使用它之前需要一些配置。
将使用它来解析之前创建的IDataProvider接口的引用,所以在客户端项目中添加了一个新的app.config文件,并添加了以下配置:
这简单地在IDataProvider和EFCodeFirstDataProvider之间添加了一个映射,允许将前者解析为后者。
需要一种在应用程序中引用这个容器的方法,所以使用了一个工厂类,它有一个静态成员来保存实际的UnityContainer:
class ContainerFactory
{
private static UnityContainer container;
public ContainerFactory()
{
if (container == null)
{
container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(container);
}
}
public UnityContainer Container
{
get { return container; }
}
}
然后,可以在视图模型中有一个IDataProvider的引用,并从构造函数中解析它,如下所示:
ContainerFactory factory = new ContainerFactory();
provider = factory.Container.Resolve();
整个视图模型,包括属性,现在看起来像这样:
public class ArtistListViewModel : INotifyPropertyChanged
{
private IDataProvider provider;
private ObservableCollection artists;
private Artist selectedArtist;
private Album selectedAlbum;
public ArtistListViewModel()
{
ContainerFactory factory = new ContainerFactory();
provider = factory.Container.Resolve();
GetArtists();
}
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection Artists
{
get { return artists; }
private set { artists = value; Notify("Artists"); }
}
public Artist SelectedArtist
{
get { return selectedArtist; }
set { selectedArtist = value; Notify("SelectedArtist"); }
}
public Album SelectedAlbum
{
get { return selectedAlbum; }
set { selectedAlbum = value; Notify("SelectedAlbum"); }
}
private void GetArtists()
{
Artists = new ObservableCollection(provider.GetArtists());
}
private void Notify(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
现在已经有了视图模型和视图,需要将它们连接起来。这只是一个设置视图的DataContext的问题,从它的构造函数开始。
public ArtistList()
{
InitializeComponent();
this.DataContext = new ArtistListViewModel();
}