This site uses cookies to deliver our services. By using this site, you acknowledge that you have read and understand our Cookie and Privacy policy. Your use of Kontext website is subject to this policy. Allow Cookies and Dismiss

在Windows Phone 7.1 应用程序中实现MVVM设计模式以及使用Prism

433 views 7 comments last modified about 7 years ago Raymond Tang

In this page

MVVM设计模式是Model-View-ViewModel的简写,它从MVP(Model-View-Presenter)演变而来;使用MVVM模式可以很容易的将程序中的数据与用户界面分离,这样程序员可以更好的编写数据模型,而美工则可以创建用户界面。从程序维护、更新等方面考虑,MVVM模式也许使得我们的工作变得更加的容易。在Windows Phone应用程序中,Model即为我们的数据模型,即为一个类,View则是XAML用户控件,ViewModel也为一个类,它将View和Model联系起来。

本文将演示如何在Windows Phone应用程序中实现MVVM模式,更多参考资料请查看:

1)Implementing the Model-View-ViewModel Pattern in a Windows Phone Application

2)WPF Apps With The Model-View-ViewModel Design Pattern

3)MVVM Light Toolkit

1.创建Windows Phone Application MvvmSample

2.添加View、Model、ViewModel文件夹

3.创建数据模型Article

Article类实现了INotifyPropertyChanged接口,当其属性值发生变化时可以通知视图这些变化,以便其作相应的更改;在本程序中,用户仅能更改IsRead属性:

namespace MvvmSample.Model
{
    public class Article : INotifyPropertyChanged
    {
        /// <summary>
        /// Article ID
        /// </summary>
        public int ID { get; set; }

        /// <summary>
        /// Article Title
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// Whether this article is read
        /// </summary>
        private bool m_IsRead;
        public bool IsRead
        {
            get { return m_IsRead; }
            set
            {
                m_IsRead = value;
                RaisePropertyChanged("IsRead");
            }
        }

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}

4.创建ViewModel ArticleViewModel

ArticleViewModel包含了Model即Article的集合,保存在一个ObservableCollection集合中,这样便于当数据发生更改,View可以做相应的变化;而Article数据则通过LINQ to XML从我们上一个例子中的XML文件中读取。

XML文件内容如下:

<?xml version="1.0" encoding="utf-8" ?>
<Articles>
  <Article ID="1" IsRead="True">
    <Title>Article Title 1</Title>
  </Article>
  <Article ID="2" IsRead="True">
    <Title>Article Title 2</Title>
  </Article>
  <Article ID="3" IsRead="False">
    <Title>Article Title 3</Title>
  </Article>
  <Article ID="4" IsRead="False">
    <Title>Article Title 4</Title>
  </Article>
  <Article ID="5" IsRead="False">
    <Title>Article Title 5</Title>
  </Article>
</Articles>

ArticleViewModel代码如下:

namespace MvvmSample.ViewModel
{
    public class ArticleViewModel
    {
        /// <summary>
        /// All the articles
        /// </summary>
        public ObservableCollection<Article> AllArticles { get; set; }

        /// <summary>
        /// Constructor
        /// </summary>
        public ArticleViewModel()
        {
            Initialize();
        }

        /// <summary>
        /// Initialize the list
        /// </summary>
        private void Initialize()
        {

            //load all xml via LINQ to XML
            XDocument doc = XDocument.Load("Data\\Articles.xml");
            var articles = from article in doc.Root.Elements("Article")
                           select new Article
                           {
                               ID = Convert.ToInt32(article.Attribute("ID").Value),
                               Title = article.Element("Title").Value,
                               IsRead = Convert.ToBoolean(article.Attribute("IsRead").Value)
                           };
            this.AllArticles = new ObservableCollection<Article>(articles.ToList<Article>());
        }
    }
}

5.创建View ArticleView.xaml

在View文件夹下创建Windows Phone User Control ArticleView.xaml。在<Grid x:Name="LayoutRoot">元素中添加以下代码:

<ListBox ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50"/>
                            <ColumnDefinition Width="250"/>
                            <ColumnDefinition Width="50"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock x:Name="ID" Text="{Binding Path=ID, Mode=OneWay}" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        <TextBox x:Name="Title" Text="{Binding Path=Title, Mode=OneWay}" Grid.Column="1" TextAlignment="Center" InputScope="Number"/>
                        <CheckBox x:Name="IsRead" IsChecked="{Binding Path=IsRead, Mode=TwoWay}"Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

6.在MainPage中添加ArticleView

生成项目,添加命名空间my,xmlns:view="clr-namespace:MvvmSample.View",在Grid中添加ArticleView元素:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <view:ArticleView HorizontalAlignment="Left" Margin="0,0,0,0" x:Name="articleView1" VerticalAlignment="Top" DataContext="{Binding}" />
        </Grid>

添加命名空间xmlns:vm="clr-namespace:MvvmSample.ViewModel",在资源中添加ViewModel: 

<phone:PhoneApplicationPage.Resources>
        <vm:ArticleViewModel x:Key="viewModel"/>
    </phone:PhoneApplicationPage.Resources>

设置articleView1的DataContext为viewModel:

<view:ArticleView HorizontalAlignment="Left" Margin="0,0,0,0" x:Name="articleView1" VerticalAlignment="Top" DataContext="{Binding Source={StaticResource viewModel}}" />

最终整个项目结构如下:

在Windows Phone Emulator中运行效果如下:


7.测试INotifyPropertyChanged

为了测试INotifyPropertyChanged是否发生作用,接下来我们再ArticleView.xaml中添加一个按钮Add,其作用为,当鼠标点击此按钮后,向View
Model的集合中添加一条新的Article数据。

XAML改动如下:

<StackPanel Orientation="Vertical">
            <ListBox ItemsSource="{Binding Path=AllArticles}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="50"/>
                                <ColumnDefinition Width="250"/>
                                <ColumnDefinition Width="50"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock x:Name="ID" Text="{Binding Path=ID, Mode=OneWay}" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            <TextBox x:Name="Title" Text="{Binding Path=Title, Mode=OneWay}" Grid.Column="1" TextAlignment="Center" InputScope="Number"/>
                            <CheckBox x:Name="IsRead" IsChecked="{Binding Path=IsRead, Mode=TwoWay}" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <Button Content="Add" Height="72" HorizontalAlignment="Left" Margin="0,0,0,0" Name="buttonAdd" VerticalAlignment="Top" Width="160" Command="{Binding  Path=AddCommand}" />
        </StackPanel>

为了实现命令的绑定,我们通过Prism来实现,下面将参数如何安装Prism。

8.安装Prism

右击Reference,选择Add Library Package Reference:

在弹出对话框中,搜索prism,点击安装按钮:

安装完成后,可以看到项目中,增加了对Prism相应组件的引用:

9.修改ArticleViewModel

在ArticleViewModel中增加一个属性AddCommand,类型为ICommand,用于Add按钮的绑定,增加以及变化的代码如下:

/// <summary>
        /// Add command
        /// </summary>
        public ICommand AddCommand { get; private set; }
        /// <summary>
        /// Constructor
        /// </summary>
        public ArticleViewModel()
        {
            Initialize();
            this.AddCommand = new DelegateCommand<Object>((obj) =>
            {
                this.AllArticles.Add(new Article()
                {
                    ID = AllArticles.Last<Article>().ID + 1,
                    Title = string.Format("Article Title {0}", AllArticles.Last<Article>().ID + 1),
                    IsRead = false
                });
            },
            (arg) => true);
        }

在Emulator中运行效果:

点击Add按钮,ListBox会自动的刷新并且增加新的纪录:

以上结果表明ObservableCollection生效;按照同样的方式,我们添加一个Change按钮,更改列表数据中最后一项的CheckBox的状态。

改动的代码如下:

/// Change command
        /// </summary>
        public ICommand ChangeCommand { get; private set; }
构造函数增加:

this.ChangeCommand = new DelegateCommand<Object>((obj) =>
            {
                if (this.AllArticles.Count > 0)
                {
                    var article = this.AllArticles.Last<Article>();
                    article.IsRead = article.IsRead ? false : true;
                }
            },
            (arg) => true);

运行效果如下,点击Change按钮,最后一项的IsChecked即会发生相应的变化:

由此可见,IsRead属性也已经生效。

 

本文为原创文章,若需转载,请注明来源http://hi.baidu.com/1987raymond, 若需要本文源码,请回复你的邮箱,或者发邮件到我的邮箱china.raymond[at]hotmail.com。

Related pages

Surface RT/Pro 版本Windows 8 QQ下载与安装

2515 views   0 comments last modified about 5 years ago

Surface的用户可能会遇到一个难题,在应用商城里边无法搜索到QQ应用程序。但是让我疑惑的是,我的Windows 8.1 系统之前是成功安装了QQ。

后来在腾讯QQ下载官网发现,其实是有QQ应用安装的链接:

按照如下方法安装Surface QQ.

Have fun!

image

View detail

my first begining with Windows 7

101 views   0 comments last modified about 9 years ago

Maybe it is a little late now due to busy work,anyhow,it is better to do lately than never to do.

View detail

[教程]在Windows Phone 程序中使用LINQ to XML以及执行数据绑定

260 views   0 comments last modified about 7 years ago


LINQ是Language Integrated Query的简写,中文名称是语言集成查询,它是一组技术的组合,包括LINQ to DataSet(typed 以及untyped),LINQ to SQL(适用于SQL Server数据库),LINQ to XML(包括内存中以及XML文件中的数据),LINQ to Object,LINQ to Entities(结合Entity Framework使用)等。这些技术建立在将查询功能直接集成到 C# 语言(以及 Visual Basic 和可能的任何其他 .NET 语言)的基础上。借助于 LINQ,查询现在已是高级语言构造,就如同类、方法、事件等等。具体参考MSDN文档介绍View detail

SVN 中文子目录权限失效的解决方案

241 views   0 comments last modified about 9 years ago

svn对于非英文文件名和目录名使用utf-8格式编码处理,要对中文目录进行正确控制,
对于authz文件应该使用无BOM的utf-8格式,如何将默认的文件转为utf-8?可以使用UltraEdit编辑器存储的时候把格式选择“UTF-8 无BOM”;

View detail

LINQ to SQL in Windows Phone 7 Error: An overflow occurred while converting to datetime.

454 views   0 comments last modified about 7 years ago

Resolve the issue in Linq to SQL in Windows Phone 7 App:
An overflow occurred while converting to datetime.

View detail

Add comment

Please login first to add comments.  Log in New user?  Register

Comments (7)

R Re:在Windows Phone 7.1 应用程序中实现MVVM设计模式以及使用Prism

Ra*** about 6 years ago

@ifree 谢谢捧场 现在实现了邮件功能,回复可以直接发送到你的邮箱

if*** about 7 years ago

你看你博客连个留言的地方都不留一个,到这里来给你捧场了. 哈哈
ps. 配一个openid插件嘛
RT Re:在Windows Phone 7.1 应用程序中实现MVVM设计模式以及使用Prism

Raym*** about 6 years ago

@wingyiu ICommand class可以参看此MSDN帮助文档http://msdn.microsoft.com/zh-cn/library/vstudio/system.windows.input.icommand(v=vs.95).aspx

wi*** about 6 years ago

SL4已经提供ICommand了,不用Prism了
R Re:在Windows Phone 7.1 应用程序中实现MVVM设计模式以及使用Prism

Ra*** about 6 years ago

@wingyiu SL4里面的东西没去了解
W Re:在Windows Phone 7.1 应用程序中实现MVVM设计模式以及使用Prism

wi*** about 6 years ago

SL4已经提供ICommand了,不用Prism了
R re: 在Windows Phone 7.1 应用程序中实现MVVM设计模式以及使用Prism

Ra*** about 7 years ago

This is just test for emailing
R re: 在Windows Phone 7.1 应用程序中实现MVVM设计模式以及使用Prism

Ra*** about 7 years ago

与我联系那里就可以留言呢
谢谢捧场 :)
OpenID 插件之前没整过 虽然这个是支持的
I re: 在Windows Phone 7.1 应用程序中实现MVVM设计模式以及使用Prism

if*** about 7 years ago

你看你博客连个留言的地方都不留一个,到这里来给你捧场了. 哈哈
ps. 配一个openid插件嘛