silverlight 页面之间的导航汇总
在网上搜了几个silverlight页面导航的几个帖子,在这里汇总一下。
1、 Silverlight: How to do navigation easily (Gill Cleeren)讲的是Silverlight 1.1中做页面导航
Here's a trick to a question I have heard a few times already: how to perform easy navigation in Silverlight 1.1?
我已经听过很多次关于如何在silverlight1.1中导航的技巧的问题?
This problem can be partially solved using hidden panels: you click on a button, Panel1 is hidden and Panel2 becomes visible. This is a trick that is often done in ASP.net too.
这个问题可以用隐藏panels(翻译成面板?)的方式实现,点一下按钮,面板1隐藏,面板2显示。这个技巧也经常被用在ASP.net中。
Well, this trick can also be done in Silverlight, using the Control class. This class makes it possible to have a piece of XAML that has been loaded dynamically, act as a Control, that can be shown or hidden to do navigation (or actually, fake navigation).
ok,这个技巧也可以用在Silverlight中,使用控件类。这个类可以动态加载一个XAML作为控件,然后显示或者隐藏实现导航的效果(其实是假的导航)。
Consider the following code. I have a panel, Panel1, that inherits from Control. Inside the constructor, XAML is read from a resource (ie, a XAML file).
考虑一下下面的代码,panel1继承自Control类。在panel1类的构造器中读取XAML资源。(例如:XAML文件)
public class Panel1 : Control { FrameworkElement myPanel; Rectangle button; public Panel1() { System.IO.Stream s = this.GetType().Assembly.GetManifestResourceStream("App1.MyPanel.xaml"); button = this.InitializeFromXaml(new System.IO.StreamReader(s).ReadToEnd()); button = (Rectangle)myPanel.FindName("button"); } }
Now, in the main code behind page, we'll instantiate the constructor of the Panel1 class, and we'll add the controls it generates dynamically (from the XAML that is) to the existing XAML.
在主页的后台代码中,实例化这个Panel1并动态添加到已存在的XAML中。
Panel1 p = new Panel1(); this.Children.Add(p); //If we later want to remove the panel, the following line does the trick. this.Children.Remove(p); 2、silverlight2.0 页面跳转 (csdn中的ourmessage)
这个汉语的看起来不像英语那么费力了,呵呵。原文章有图,不知道怎么加图。推荐看原帖:http://blog.csdn.net/ourmessage/archive/2008/03/12/2172431.aspx
我新建了一个项目,里面有已经有一个页面(Page)了,如果需要跳转到另一页面,就需要在项目上点右键,找到 "Add Silverlight Link ",在弹出窗体中选择新建一个silverlight项目并添加到解决方案中,
如果要第一个页面跳转到第二个页面,只需要在第一个页面加入如下代码:
HtmlWindow html = HtmlPage.Window;
html.Navigate(new Uri("http://localhost:4535/sildemo_Web/otherTestPage.aspx"));
将第二个页面的url指定进来! (http://localhost:4535/sildemo_Web/otherTestPage.aspx)
以下为个人理解:
当时我也没想明白为什么要这么做,后来仔细看了一下代码,
public partial class Page : UserControl{
…….
}
代码里面是我们的sl是继承自UserControl,而不是继承自Page或者Canvas.
那么从逻辑上来讲,它既然是派aspx页面下的一个控件,那么它就会理由去负责页面的导航问题,因为它至少应该属于Frame(框架)级别的类或者是当前浏览器的Page(页面)级的类,而这里它只是一个控件,因此,它进行跳转需要能过别的类来完成这样的工作.
这样我们就可以很好理解为什么没看到我们的(Page : UserControl),page对象没有包含跳转.或者导航这样的方法.
html.Navigate(new Uri("otherTestPage.aspx",UriKind.Relative));
这样,就可以使用相对路径了
3、Silverlight 2 Navigating Between Xaml Pages (March 21, 2008 09:23 by Sean)
One of the problems I've run across while playing around with the Beta is the lack of support for any easy way to navigate around you application by moving between Xaml pages. The problem really stems from this little piece of generated code in your App.xaml.cs file.
在我使用beta的一个问题,在两个Xaml页面导航之间缺乏一种简单的方法的支持。这个问题源自自动生成的app.xaml.cs文件。
private void Application_Startup(object sender, StartupEventArgs e) { // Load the main control this.RootVisual = new Page(); }
Looking at the docs for the RootVisual property of Application class, we're told that RootVisual can only be set once. My limited testing shows that this isn't actually true, and that it's possible to set LayoutRoot as many times as you'd like but only in the Application_Startup handler, which is obviously of very little use!
查看应用程序类RootVisual属性的文档中,告诉我们RootVisual只能被设置一次。在我有限的试验中它不真正是这样的。只是设置LayoutRoot的Application_Startup不能多次(英语太差,实在不理解这句话的意思是Application_Startup设置一次还是多次),他显然很少用到。
My solution is actually really very simple and can be summed up with one short snippet of code...
我的解决方案其实很简单,可以归纳为一个小代码段:
private void Application_Startup(object sender, StartupEventArgs e) { // Load the main control Grid root = new Grid(); root.Children.Add(new Page()); this.RootVisual = root; }
As you can see, here I am setting the RootVisual of the application as a new Grid and adding my Page usercontrol as a child of the grid. All we need to do now when we want to switch out Xaml pages is to manipulate the Children collection of our Grid! Here, check out my demo to see how it looks in action, this is a little two page application which allows you to switch back and forth between the pages in a number of different ways.
你可以看到,这里我设置了程序的RootVisual为一个新的Grid并添加了自己的page也作为Grid的子控件。当我要选择我们自己的Xaml Pages,我们所需要的操作就是在我们的Grid中操作子控件集。下载我的Demo看他如何操作,这个小的有两个Xaml页的程序允许我们用几种不同的效果在这两个页面中切换。
Woah! Hang on, where did all those cool transition effects come from? It just so happens that I've knocked together a few classes (I'm not going to use the word 'framework'!) that make these navigation issues and transition effects, even making your own transitions, really really easy. So... On to the code.
哇哦!继续,所有的这些酷酷的切换效果哪里来的呢?他只发生在我敲的几个类中(我不打算用framework这个词),他们负责导航和切换效果,甚至使用在你自己的切换中,他们是真的真的很简单。so...,看代码。
First up we'll take a look at the transitions. Every transition is implemented as a class deriving from the abstract TransitionBase, it's a really tiny little class which provides the implementation for a completed event, for when the transition has finished, and the contract for a single method which must be implemented by derived transitions.
首先,我们考虑一下切换,每个切换类实现了抽象类TransitionBase,他提供了completed方法的实现当切换完成时,声明了这个单一方法必须被派生类实现。
public abstract class TransitionBase { public event EventHandler<TransitionCompletedEventArgs> TransitionCompleted; protected void OnTransitionCompleted(UserControl newPage, UserControl oldPage) { if (TransitionCompleted != null) TransitionCompleted(this, new TransitionCompletedEventArgs() { NewPage = newPage, OldPage = oldPage }); } public abstract void PerformTranstition(UserControl newPage, UserControl oldPage); }
We have a PerformTransition method here which takes a reference to the two pages, the current and the one we'd like to change it with. This method is obviously implemented by our derived transitions to manipulate and animate the pages in some pleasing way, one thing to note here is that when the transition has completed its shuffling of the pages around, it must fire the completed event as we will see shortly.
PerformTransition 方法的参数为两个Xaml页,当前页和我们要切换到的页。这个方法显然要实现在我们派生的切换类的操作和动画。要注意的一件事情是,当切换完成时必须激发完成事件。
Next up lets look at NavigationHelper, this is a static class which contains methods which can be called to switch pages.
下一步,看看NavigationHelper类,这是个静态类提供被交换页调用的方法。
public static class NavigationHelper { private static Grid root; static NavigationHelper() { root = Application.Current.RootVisual as Grid; } public static void Navigate(TransitionBase transition, UserControl newPage) { UserControl oldPage = root.Children[0] as UserControl; root.Children.Insert(0, newPage); transition.TransitionCompleted += transition_TransitionCompleted; transition.PerformTranstition(newPage, oldPage); } public static void Navigate(UserControl newPage) { UserControl oldPage = root.Children[0] as UserControl; root.Children.Add(newPage); root.Children.Remove(oldPage); } private static void transition_TransitionCompleted(object sender, TransitionCompletedEventArgs e) { root.Children.Remove(e.OldPage); } }
Ok, so here in our static constrcutor we grab a reference to our root visual from the application object. This is cast to a Grid so we can manipulate the Children collection. Now this is not really 100% safe because our static constructor will run the first time and member of our NavigationHelper class is accessed and this could be before the application's root visual has been set as a Grid. In practice though this is very unlikely to ever happen and it would make no sense at all for someone to call our navigation methods before Application_Startup so I'm going to let it go...
ok,看都看的迷迷糊糊,翻译更不会了。
We also have two methods here, one which take a TransitionBase and a UserControl and one which just takes a UserControl. The method taking just a UserControl simply switches out the Xaml pages with no other action. The method first gets a reference to the current page which should be at the top of the children collection, then it inserts our new page at the top, this will cause it to be visible and hide the previous page as we have dropped our new one on top, the final step is to pull out the old page from underneath. This is how the "Switch" button in the demo above is working...
The other Navigate overload is more interesting, first we get a reference to the old page but this time we insert the new page behind it so it isn't immediately visible. Next we subscribe to the completed event for the passed in transition object and fire it off to let it do it's thing. We can see that when the transition completes and fires it's event, we simply remove the old page.
Looks great! Now we'll check out how a transition is implemented. There are a few transitions included with the code, but it's really easy for you to write your own and pass them to the NavigationHelper.Navigate method, just by inheriting from TransitionBase. Here is my FadeTransition.
public class FadeTransition : TransitionBase { private UserControl newPage; private UserControl oldPage; private TimeSpan time; public FadeTransition(TimeSpan duration) { time = duration; } public FadeTransition() : this(TimeSpan.FromSeconds(2)) { } public override void PerformTranstition(UserControl newPage, UserControl oldPage) { this.newPage = newPage; this.oldPage = oldPage; Duration duration = new Duration(time); DoubleAnimation animation = new DoubleAnimation(); animation.Duration = duration; animation.To = 0; Storyboard sb = new Storyboard(); sb.Duration = duration; sb.Children.Add(animation); sb.Completed += sb_Completed; Storyboard.SetTarget(animation, oldPage); Storyboard.SetTargetProperty(animation, "Opacity"); oldPage.Resources.Add(sb); sb.Begin(); } void sb_Completed(object sender, EventArgs e) { OnTransitionCompleted(newPage, oldPage); } }
This first thing to notice is that we overload the constructor so that we can pass in timespan, this lets us lengthen or shorten the transition as we see fit. Next is the PerformTransition implementation, this method just steps through and constructs a Storyboard object in code then sets it to run. When the Storyboard has finished its work we fire the TransitionCompleted event which lets NavigationHelper clear up out old page. I won't step through how the Storyboard is created as it's well documented on MSDN and I pretty much just copied if from there anyway, so if you want to know more, go check it out.
There is one other transition I'd like to show you, which is called CompositeTransition. This is how I achieve multiple effects at once, for example fading and sliding. I create a fade transition and a wipe transition, wrap them in a CompositeTransition and pass that to the NavigationHelper.
public class CompositeTransition : TransitionBase { private TransitionBase transitionOne; private TransitionBase[] transitions; private Int32 count; private UserControl newPage; private UserControl oldPage; public CompositeTransition(TransitionBase transitionOne, params TransitionBase[] transitions) { this.transitionOne = transitionOne; this.transitions = transitions; } public override void PerformTranstition(UserControl newPage, UserControl oldPage) { this.newPage = newPage; this.oldPage = oldPage; transitionOne.TransitionCompleted += transition_TransitionCompleted; transitionOne.PerformTranstition(newPage, oldPage); foreach (TransitionBase transition in transitions) { transition.TransitionCompleted += transition_TransitionCompleted; transition.PerformTranstition(newPage, oldPage); } } private void transition_TransitionCompleted(object sender, TransitionCompletedEventArgs e) { count++; if (count == transitions.Length + 1) OnTransitionCompleted(newPage, oldPage); } }
There is nothing particularly clever going on here, we have a constructor which take a variable number of TransitionBase instances. When PerformTransition is called we fire off all the transitions at once. When each one of them has completed we fire the TransitionCompleted event. Nice, now we can create loads of cool stuff! One thing worth noting though when stringing transition together like this, in my implementation there is a limitation in that my transtions set the UserControl's RenderTransform property and animate on this. If you chain multiple transitions which work like this they will over write the UserControls RenderTransform and only the last transition will do anything. The fix for this I guess would be to pass a TransformGroup into each transition so they're all animating against the same instance, but I'll leave that bit of fun and games as an excercise for the reader!
Just quickly, here is a snipet showing what a call to NavigationHelper.Navigate looks like, and then I'll leave you with the code download.
TransitionBase transition = new CompositeTransition( new FadeTransition(TimeSpan.FromSeconds(1)), new WipeTransition(WipeTransition.WipeDirection.LeftToRight)); NavigationHelper.Navigate(transition, new AnotherPage());
Enjoy!
FlawlessCode.Navigation.zip (144.27 kb)
4、其他网上看了跟切换页面有关的内容。
a、切换页面总要传递一点相关的数据,一个方法可以用cookie。读取cookie的方法
http://www.eggheadcafe.com/community/aspnet/12/10032919/cookies-problem-in-silver.aspx
using System.Windows.Browser; string str = string.Empty; str = HtmlPage.Document.Cookies; Empid = str.Split('=')[1]; } private static string _empid = string.Empty; public static string Empid { get { return UserDetails._empid; } set { UserDetails._empid = value; } } 说是有个问题就是刷新了cookie里的值后不能读出新值,先记着,慢慢研究。
b、Xaml页面和html页面切换出现的问题
http://silverlight.net/forums/t/3917.aspx
c、还有一些人在silvernight中提的问题,这里把链接记下来慢慢研究
Multiple Silverlight 2.0 controls on same ASP .NET page
http://silverlight.net/forums/t/15643.aspx
Problem testing splash screen
http://silverlight.net/forums/t/15672.aspx
How to use multiple Silverlight applications in one .xap file