posts - 6,  comments - 13,  trackbacks - 0

这几天偶染小恙,今天继续MVVM。

1、创建工程

首先先用VS2010新建一个Silverlight Application,

不要建立一个新的Web站点,我们使用OOB

然后更改工程的属性,添加OOB支持并增加信任权限,

此时在VS中F5运行,不会启动浏览器,而是直接以OOB方式启动应用。

2、设计界面

用Blend打开工程(为什么用Blend,因为MVVM的主要目标就是分离UI和UI逻辑,UI由美工设计,UI逻辑由程序员完成,这样就避免了程序员设计界面或者美工设计程序的苦恼),然后在工程中添加"UserControl with ViewModel",文件名改为FeedsView.xaml,

这个View用于显示每个订阅的名称。同理添加FeedItemsView用于显示每个订阅的新闻标题。

编译工程,打开MainPage.xaml,在Assets页中找到Locations->SilverReader.xap,

可以看见右侧显示了3个UserControl,把FeedsView和FeedsItemsView拖到MainPage中,然后调整一下布局,下面是XAML代码:

MainPage.xaml
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d
="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc
="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local
="clr-namespace:SilverReader" x:Class="SilverReader.MainPage"
mc:Ignorable
="d"
d:DesignHeight
="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>

<local:FeedsView/>
<local:FeedItemsView Grid.Column="1"/>

</Grid>
</UserControl>

 

 

我只是简单的使用了左右布局,MainPage不是主要的UI,充其量算UI的一个容器,真正的UI设计是在其他的两个View中。

3、FeedsView

下面是FeedsView的设计界面,

对象结构如下:

在第一行有一个Button用于显示第二行的UI,第二行包括一个TextBox用于输入RSS的网址和一个Button,第三行只是一个简单的ListBox,显示我们订阅的RSS标题。第二行平时应该是隐藏的,只有点击的第一行的Button后才应该显示,所以更改第二行的Grid的Visibility属性的值为Collapsed。

下一步要添加"添加订阅"Button的行为,当点击Button时,第二行的TextBox和Button能够显示,也就是将上述的Visibility属性改为Visible。以前的方法是直接双击Button,然后在后台代码中编写事件响应函数。现在依赖Blend的Behaviors,不用写一行代码就可以做到了。

首先在Blend的Assets中选择Behaviors->ChangePropertyAction,拖到"添加订阅"Button上,

然后设置Action的属性,TargetObject为第二行的Grid,PropertyName为Visibility,Value为Visible。

4、FeedsViewModel

下面就该ViewModel了,现在的ViewModel中还没有任何东西,先添加一个Feed的集合,还要让ViewModel实现INotifyPropertyChanged接口,代码如下:

FeedsViewModel
public class FeedsViewModel : INotifyPropertyChanged
{
public ObservableCollection<SyndicationFeed> Feeds { get; private set; }

#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(
this, new PropertyChangedEventArgs(info));
}
}
#endregion
}

 

5、添加设计数据

在Blend中选择Data页,添加一个新的Sample Data,

 

选择FeedsViewModel类,在工程中添加FeedsViewModelSampleData.xaml,

6、显示Feed标题

在FeedsView中的ListBox下添加ItemTemplate,用一个TextBox显示Title.Text,代码如下:

代码
<ListBox Grid.Row="2" ItemsSource="{Binding Feeds}">
<ListBox.Resources>
<DataTemplate x:Key="ListItemTitleTemplate">
<StackPanel>
<TextBlock TextWrapping="Wrap" Text="{Binding Title.Text, Mode=OneWay}"/>
</StackPanel>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<StaticResource ResourceKey="ListItemTitleTemplate"/>
</ListBox.ItemTemplate>
</ListBox>

 

 

然后选择"LayoutRoot"Grid,设置DataContent:

此时在设计界面就可以看见显示的结果了。

7、添加命令

在FeedsView中的"添加"Button下添加InvokeCommandAction,绑定Action的Command属性为AddFeedCommand

绑定Action的CommandParameter属性为TextBox的Text属性

然后在FeedsViewModel中添加如下代码:

代码
public FeedsViewModel()
{
Feeds
= new ObservableCollection<SyndicationFeed>();
AddFeedCommand
= new ActionCommand(delegate(object o)
{
string url = (string) o;
Uri feedUri;
Uri.TryCreate(url, UriKind.Absolute,
out feedUri);
if (feedUri == null)
return;
WebClient request
= new WebClient();
request.DownloadStringCompleted
+=
delegate(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
return;

string xml = e.Result;
if (xml.Length == 0)
return;

StringReader stringReader
= new StringReader(xml);
XmlReader reader
= XmlReader.Create(stringReader);
SyndicationFeed feed
= SyndicationFeed.Load(reader);

if (Feeds.Where(f => f.Title.Text == feed.Title.Text).ToList().Count > 0)
return;

Feeds.Add(feed);

};
request.DownloadStringAsync(feedUri);

});
}

public ObservableCollection<SyndicationFeed> Feeds { get; private set; }
public ICommand AddFeedCommand { get; private set; }

 

 

最后,看一下运行效果(从VS2010中启动)

8、总结

MVVM模式的主要要点:

  1. View的设计只是对XAML文件的编辑(通过GUI或者编辑器),没有后台代码,一般是由美工完成;
  2. ViewModel类直接对应View,View需要显示什么,ViewModel就提供什么,一般由程序员完成;
  3. ViewModel绑定到View的DataContent属性;
  4. 用户输入可以通过Blend提供的Behavior绑定到ViewModel上
  5. 通过d:DataContext和d:DesignData可以绑定设计时间数据,在设计器中就可以预览界面效果

实际上只是试验了MVVM中的V和VM,下一次结合FeedItemsView的实现试验Model。

源码可以从github上下载。

posted on 2010-09-26 15:01 DarthVader 阅读(...) 评论(...) 编辑 收藏