Silverlight Navigation(多页面切换、传值)(一)
导航.简单的理解可以是从一个页面跳转到另外一个页面。在传统的ASP.NET网站中这种效果很容易实现。而在Silverlight中我们也同样可以,我们有两种方法来实现这个效果。
第一个选择是使用代码更改页面视图(修改容器Content属性),移除/添加User Control来实现导航,这个方法比较简单、直接代码量也很少。并且在这个过程中还可以加入动画、变形等效果。
第二个选择就是使用Silverlight的导航系统,导航系统包含两个主要的控件:Frame、Page。基本的效果是可以在一个Frame里面切换多个页面(UserControl、Page)。
此次先简单介绍下第一种方法。 简单的页面切换效果:
这个例子,将页面分成上下两部分,上面表示菜单,下面放置一个容器空间用于承载内容。容器控件你可以旋转Border、ScrollViewer、StackPanel、Grid。下面是主页面的代码:
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="6*"></RowDefinition>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" SelectionChanged="lstPages_SelectionChanged">
<!--页面列表-->
</ListBox>
<basics:GridSplitter Grid.Row="1" Margin="0 3" HorizontalAlignment="Stretch"
Height="2"></basics:GridSplitter>
<Border Grid.Row="2" BorderBrush="SlateGray" BorderThickness="1"
x:Name="mainFrame" Background="AliceBlue"></Border>
</Grid>
这个例子中使用Border作为容器命名为mainFrame,在页面加载的时候先为容器加入一个页面(为项目添加2个以上UserControl):
Page1 page1 = new Page1();
mainFrame.Child = page1;
这里的容器控件是多选的,你也可使用单行单列的Grid。下面为ListBox加入事件代码:
private void lstPages_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//获取当前的Item
string newPageName = ((ListBoxItem)e.AddedItems[0]).Content.ToString();
//根据名称使用反射创建一个UserControl实例
Type type = this.GetType();
Assembly assembly = type.Assembly;
UserControl newPage = (UserControl)assembly.CreateInstance(
type.Namespace + "." + newPageName);
//加入到容器中.
mainFrame.Child = newPage;
}
至此一个简单的页面切换效果就OK了。这个DEMO的效果图如下:
●使用根视图(Root Visual)
上面是一个简单的例子,这个方法很常见,但不是通用方式。它的小缺陷是整个页面布局已经固定死了,工具栏或页面始终都固定在那里,那如果你想要的是一个全新的页面就不行了。下面对这个小例子进行一下扩展就可以达到我们的目的了。
首先在App.xaml.cs中声明一个Grid:
private Grid rootGrid = new Grid();
然后修改Appliaction_Startup事件代码:
this.RootVisual = rootGrid;
rootGrid.Children.Add(new Page1());
这样只能保证在初始化的时候会有一个页面而不能导航,为此在App.xaml.cs代码中加入一个静态方法,代码如下:
public static void Navigation(UserControl newPage)
{
//获取当前的Appliaction实例
App currentApp = (App)Application.Current;
//修改当前显示页面内容.
currentApp.rootGrid.Children.Clear();
currentApp.rootGrid.Children.Add(newPage);
}
这里要注意 方法的参数是UserControl。这样在你的UserControl中即可添加如下的代码(可以加到button事件中)进行页面切换了:
App.Navigation(new Page2());
new的对象是你的目标页面,不要写错了。就这几句代码又完成了咱们的目的!
●保存页面状态(Cache)
如果你想让用户在返回到历史页面的时候可以页面的修改状态比如用户输入的数据。首先对项目进行一下小小的修改,添加一个名字叫Pages的enmu,用于保存页面名称以便使用字符串产生不必要的问题:
public enum Pages
{
Page1,
Page2
}
下一步是在App.cs代码中加入一个泛型集合用于保存页面:
private static Dictionary<Pages, UserControl> pageCache = new Dictionary<Pages, UserControl>();
其中Key是Pages枚举,Value是UserControl。然后从新定义Naviagte方法:
public static void Navigation(Pages newPage)
{
App currentApp = (App)Application.Current;
if (!pageCache.ContainsKey(newPage))
{
//根据名称使用反射创建目标页面实例,并加入缓存
Type type = currentApp.GetType();
Assembly assembly = type.Assembly;
pageCache[newPage] = (UserControl)assembly.CreateInstance(
type.Namespace + "." + newPage.ToString());
}
currentApp.rootGrid.Children.Clear();
currentApp.rootGrid.Children.Add(pageCache[newPage]);
}
这样在其他的UserControl中调用如下代码就可以进行切换了:
App.Navigation(Pages.Page2);
如果在页面中放置一个文本框然后输入值,跳转到其他页面再切换回来的话就会看到文本框的值依然存在,这是因为UserControl被保存在内存中了。效果图如下:
如果你进行切换就会发现TextBox的值依然存在.这样就实现了简单的缓存.
●页面传值:
关于页面传值我仅仅说一下我的方式,当让网上也有其他的关于页面之间传值的方法。主要是使用独立存储的IsolatedStorageSettings对象,首先在UserControl中创建对象:
private IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;然后在Button事件中加入如下代码,用于传值:
if (!appSettings.Contains("Page2"))
appSettings.Add("Page2", "UserName");
OK了,在目标页面获取值的方式就简单了.
if (appSettings.Contains("Page2"))
txbShowvalue.Text = "User Name: " + appSettings["Page2"].ToString();
需要注意的一点是这个获取值的代码不要写在页面的构造函数里面,有可能不会触发,原因是在上面对象已经保存在内存中了,但是会触发Loaded事件,因此可以把代码放到这个事件里面。最总效果如下:
你也可以使用同样的方式来给Page1传值。OK..关于第一种页面导航、传值、简单缓存,就介绍完毕..