在第二章中我们有讲到有DesignHelper类,下面是该类的源码:
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Windows;
namespace MvvmTutorial.Infrastructure
{
public static class DesignHelper
{
#region Fields
private static bool? _isInDesignMode;
private static readonly Random Rand = new Random(Guid.NewGuid().GetHashCode());
#endregion // Fields
#region Properties
/// <summary >
/// Gets a value indicating whether the control is in design mode
/// (running in Blend or Visual Studio).
/// </summary >
[SuppressMessage(
"Microsoft.Security",
"CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands",
Justification = "The security risk here is neglectible.")]
public static bool IsInDesignMode
{
get
{
if (!_isInDesignMode.HasValue)
{
#if SILVERLIGHT
_isInDesignMode = DesignerProperties.IsInDesignTool;
#else
#if WIN8
_isInDesignMode = Windows.ApplicationModel.DesignMode.DesignModeEnabled;
#else
var prop = DesignerProperties.IsInDesignModeProperty;
_isInDesignMode
= (bool)DependencyPropertyDescriptor
.FromProperty(prop, typeof(FrameworkElement))
.Metadata.DefaultValue;
// Just to be sure
if (!_isInDesignMode.Value
&& Process.GetCurrentProcess().ProcessName.StartsWith("devenv", StringComparison.Ordinal))
{
_isInDesignMode = true;
}
#endif
#endif
}
return _isInDesignMode.Value;
}
}
#endregion // Properties
#region Public Methods
/// <summary >
/// Gets a random string, given its minimum length and maximum length
/// </summary >
public static string GetRandomString(int minLen = 15, int maxLen = 50)
{
StringBuilder builder = new StringBuilder();
int length = Rand.Next(minLen, maxLen);
char ch;
for (int i = 0; i < length; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * Rand.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString().ToLower();
}
public static string GetRandomNumericString(int minLen = 15, int maxLen = 25)
{
StringBuilder builder = new StringBuilder();
int length = Rand.Next(minLen, maxLen);
for (int i = 0; i < length; i++)
{
builder.Append(Rand.Next(0, 10).ToString());
}
return builder.ToString().ToLower();
}
#endregion // Public Methods
}
}
注意IsInDesignMode属性:这是我剽窃MvvmLight的代码。它的作用在于调用它,你可以知道当前你是处于开发视图下还是runtime环境下,什么意思呢,等会儿再解释。还有一个new Contact().GenerateRandomData(),这个GenerateRandomData其实来自于一个Helper类:在Models下添加ModelHelper:
using MvvmTutorial.Infrastructure;
namespace MvvmTutorial.Models
{
public static class ModelHelper
{
public static Contact GenerateRandomData(this Contact target)
{
target.Name = DesignHelper.GetRandomString(5, 15);
target.PhoneNumber = DesignHelper.GetRandomNumericString(8, 12);
return target;
}
}
}
这个应该很容易理解,就是给一个Contact的属性添加一些随机的数据而已,这样便于我们设计和测试。有了ContactMasterViewModel,我们必然需要ContactMasterView,于是在Views下添加ContactMasterView,其XAML代码如下:
<UserControl x:Class="MvvmTutorial.Views.ContactMasterView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:MvvmTutorial.ViewModels"
mc:Ignorable="d" d:DataContext="{Binding Source={StaticResource DesignContext}}"
d:DesignHeight="300" d:DesignWidth="300" >
<UserControl.Resources >
<vm:ContactMasterViewModel x:Key="DesignContext"/ >
</UserControl.Resources >
<Grid >
<ListView ItemsSource="{Binding Items, Mode=OneWay}" >
<ListView.View >
<GridView >
<GridViewColumn Header="Name" Width="200" >
<GridViewColumn.CellTemplate >
<DataTemplate >
<TextBlock Text="{Binding Name, Mode=OneWay}" VerticalAlignment="Center"/ >
</DataTemplate >
</GridViewColumn.CellTemplate >
</GridViewColumn >
<GridViewColumn Header="Phone" Width="150" >
<GridViewColumn.CellTemplate >
<DataTemplate >
<TextBlock Text="{Binding PhoneNumber, Mode=OneWay}" VerticalAlignment="Center"/ >
</DataTemplate >
</GridViewColumn.CellTemplate >
</GridViewColumn >
</GridView >
</ListView.View >
</ListView >
</Grid >
</UserControl >
请注意d:DataContext="{Binding Source={StaticResource DesignContext}}"这里,我们给View绑上来一个DataContext,然而这只是开发视图环境下的DataContext而已。很多时候,当你做完View以后,你希望直接可以在开发视图中看到结果,这样一来你便不需要不断编译,运行,你可以很快获得修改View以后的视觉反馈(我承认我这里的中文讲话水平真的不高)。然而,还记得之前的DesignHelper.IsInDesignMode吗?它可以决定你当前是在运行程序,还是在开发视图下,如果在开发视图下,我们就给ContactMasterViewModel.Items中添加一些随机数据,如果不是开发视图,我们才真正的要从数据层返回一些真实数据(不在本章介绍数据层)。
现在还缺什么呢?ShellViewModel:在ViewModels下添加ShellViewModel:
using MvvmTutorial.Infrastructure;
namespace MvvmTutorial.ViewModels
{
public class ShellViewModel : ObservableObject
{
#region Fields
ContactMasterViewModel _contactMaster;
#endregion // Fields
#region Properties
public ContactMasterViewModel ContactMaster
{
get
{
if (_contactMaster == null)
{
_contactMaster = new ContactMasterViewModel();
}
return _contactMaster;
}
}
#endregion // Properties
}
}
将ShellView.xaml修改如下:
<Window x:Class="MvvmTutorial.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:view="clr-namespace:MvvmTutorial.Views" WindowStartupLocation="CenterScreen"
Title="Contact Book" Height="600" Width="800" >
<Grid >
<view:ContactMasterView DataContext="{Binding ContactMaster}"/ >
</Grid >
</Window >
这里应该很好理解,我们将ContactMasterView放到ShellView中,并为其指定了DataContext。那么ShellView的DataContext从哪里来呢?再次,为了简化教程,我们用一种比较天真直接的办法:修改该App.xaml.cs如下:
using System.Windows;
using MvvmTutorial.ViewModels;
using MvvmTutorial.Views;
namespace MvvmTutorial
{
/// <summary >
/// Interaction logic for App.xaml
/// </summary >
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var shell = new ShellView();
var shellViewModel = new ShellViewModel();
shell.DataContext = shellViewModel;
shell.Show();
}
}
}
现在按F5,运行程序,顺利的话,你应该可以看到一些随机数据显示在界面上。好了大体就先讲到这里。其实大家可以看到,我并没有什么奇思妙想,基本上就是一路“剽窃”各路高手的代码,然后自己拼凑了个小例子而已。编程总是有一些很固定的东西,而且这么多年来,全世界的编程高手,专家,都已经写出来许多拿来即用的东西,我们需要做的是掌握好基础,多读书,多关注新知识,然后“拿来主义”,让这些好用的工具为我们服务。
来源:http://topic.csdn.net/u/20120321/18/0d3d9cfa-346b-45b7-93d2-13eb4a69a9f7.html?seed=1362301190&r=7797
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!