现在的位置: 首页 > 综合 > 正文

WPF SDK研究 之 AppModel

2011年01月01日 ⁄ 综合 ⁄ 共 10359字 ⁄ 字号 评论关闭
这一章讲的应用程序级别的开发技术,尤其是在本章末尾,重点介绍了PageFunction<T>结构化导航,以及CustomContentState定制导航。
本章共计27个示例,全都在VS2008下.NET3.5测试通过,点击这里下载:AppModel.rar


1ActivationSample

This sample demonstrates how to handle both the Activated and Deactivated events to monitor the activation status of an application.

这个示例是在模拟一个mail系统。当窗体未被激活时,状态栏会显示代表新邮件的icon;反之,这个icon就会消失。如果熟悉事件机制,逻辑就很简单了。再有就是timerMailDispatcher中,而主逻辑和事件都在App.xaml中;MainWindow只是显示添加的新数据。这其实就是一个Observer模式。

还有,就是WPF支持的在App应用程序级别声明的4个事件:

    Startup="MyApp_Startup"               //应用程序开始,不是窗体开始
    Activated="MyApp_Activated"           //激活
    Deactivated="MyApp_Deactivated"       //未激活
    Exit="MyApp_Exit"                    //应用程序结束,不是窗体结束

示例图如下:
    
激活时的截图:
    
    未激活时的截图,注意状态栏中红色勾选的
icon,表明这是一封新mail

2ApplicationShutdownSample

This sample demonstrates the implicit and explicit mechanisms for calling Shutdown and Shutdown.

这个例子是在讲WPF中应用程序关闭的3种方式(注意,不是窗体关闭),也就是ShutdownMode3个枚举。

l         OnLastWindowClose

应用程序在最后一个窗体关闭时,或调用Shutdown方法时才会关闭

l         OnMainWindowClose

An application shuts down when either the main window closes, or Shutdown is called.

应用程序在主窗体关闭时,或调用Shutdown方法时才会关闭

l         OnExplicitShutdown

应用程序只有在调用Shutdown方法时才会关闭。

*注:这里的Shutdown方法指的是:Application.Current.Shutdown();

对于应用程序,可以这么使用:
    
Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
或者是,这里的exitCode为枚举对应的数值。
    Application.Current.Shutdown(exitCode);  

3CookieSample

This sample demonstrates how to create and retrieve cookies from a Windows Presentation Foundation (WPF) application using SetCookie and GetCookie.

主要是两个方法:
    
获取Cookie
                this.getCookieValueTextBox.Text = Application.GetCookie(cookieUri);
    
设置Cookie
                Application.SetCookie(cookieUri, this.setCookieValueTextBox.Text);

4CustomWindow

This sample shows how to implement a window that contains a custom chrome area at the top and a custom status bar at the bottom.

通过在StackPanel中指定事件:
        MouseLeftButtonDown="DragAttempt"
  
    后台代码相应为:

        private void DragAttempt(object sender, MouseButtonEventArgs e)
        
{
            
this.DragMove();
            e.Handled 
= true;
        }

从而鼠标在图中蓝色区域单击左键,然后可以拖动到任意地方。

5DispatcherUnhandledExceptionSample

This sample demonstrates how to handle DispatcherUnhandledException to process recoverable and unrecoverable unhandled application exceptions.

这个示例讲的是如何实现DispatcherUnhandledException接口,从而处理应用程序中的可恢复和不可恢复异常。

第一个按钮,使用DivideByZeroException来模拟可恢复异常
            throw new DivideByZeroException("Recoverable Exception");

第二个按钮,使用ArgumentNullException来模拟不可恢复异常
            throw new ArgumentNullException("Unrecoverable Exception");

由于在App.xaml中设置了DispatcherUnhandledException事件
    DispatcherUnhandledException="MyApp_DispatcherUnhandledException"             

后台的MyApp_DispatcherUnhandledException方法,会根据具体是哪种异常,来决定是否显示自定义对话框并关闭。逻辑很简单。关键是在窗体抛出异常的时候,在应用程序级别App.xaml通过DispatcherUnhandledException机制可以捕获到。


点击第二个按钮,弹出对话框如下:

6WindowAPI

This sample shows how to view and assign values to a variety of window properties.

要使用NavigationWindow,必须引用System.Windows.Navigation命名空间。

只有Page可以使用NavigationWindow

其它都是一些Page的属性,很简单。

7FragmentNavigationSample

This sample demonstrates how to navigate to an embedded XAML Page fragment. It also shows how to handle the FragmentNavigation event to detect when the desired fragment is not found, and override the default behavior by navigating to an error XAML Page, FragmentNotFoundPage.

这个例子的逻辑是,在文本框里输入URL,可以是外部的一个URL,也可以是DocumentPage.xaml#Fragment5这样的相对路径,其中#Fragment5指定了显示DocumentPage.xamlName="Fragment5"TextBlock。在找不到#Fragment5这样的节点时,就跳转到FragmentNotFoundPage.xaml

按下Go按钮的逻辑,执行goButton_Click方法:

       void goButton_Click(object sender, RoutedEventArgs e)
        
{
            
// Navigate to Uri, with or with out fragment
            
// NOTE - Uri with fragment looks like "DocumentPage.xaml#Fragment5"
            Uri uri = new Uri(this.addressTextBox.Text, UriKind.RelativeOrAbsolute);
            
this.browserFrame.Navigate(uri);
        }

这里browserFrameNavigate方法,会激发FragmentNavigation事件,从而执行相应的browserFrame_FragmentNavigation方法。

       void browserFrame_FragmentNavigation(object sender, FragmentNavigationEventArgs e)
        
{
            
object content = ((ContentControl)e.Navigator).Content;

            FrameworkElement fragmentElement 
= LogicalTreeHelper.FindLogicalNode((DependencyObject)content, e.Fragment) as FrameworkElement;
            
if (fragmentElement != null)
            
{
                
// Go to fragment if found
                fragmentElement.BringIntoView();
            }

            
else
            
{
                
// Redirect to error page
                this.browserFrame.Navigate(new FragmentNotFoundPage());
            }

            e.Handled 
= true;
        }

仍然是使用DispatcherUnhandledException捕获异常,在访问不到URL的时候,也就是WebException异常。



8GetSet

This sample illustrates how to get and set named application object properties.

这个例子演示了获取和设置应用程序级命名对象属性,这就像ASP中的Application级变量。

先看一下点击按钮的方法,设置了App.Current.Properties["TextFromPage1"]变量:

        void btnGoTo2(object sender, RoutedEventArgs args)
        
{
            NavigationWindow navWindow 
= (NavigationWindow)App.Current.MainWindow;
            App.Current.Properties[
"TextFromPage1"= txtBox.Text;
            navWindow.Navigate(
new Uri("Page2.xaml", UriKind.RelativeOrAbsolute));
        }

这里设置了App.Current.Properties["TextFromPage1"],同时创建了NavigationWindow对象。
创建Uri对象的语法如下:
    new Uri("Page2.xaml", UriKind.RelativeOrAbsolute)

第二个页面在初始化中,从App.Current.Properties["TextFromPage1"]变量中获取值。

        void Init(object sender, RoutedEventArgs args)
        
{
            
string appPropertyValue;
            appPropertyValue 
= (String)App.Current.Properties["TextFromPage1"];
            txtFromPage1.Text 
+= appPropertyValue;
        }


点击“
Go To Page2”按钮后,跳转到第二个页面:

9ThemedApplicationSample

This sample illustrates how to implement an application that supports dynamically-swappable themes.

这个例子的逻辑是,点击NewChildWindow按钮,新打开的子窗体会使用当前选择的Theme作为背景色。选择不同的Theme,主窗体背景色改变的同时,子窗体也会跟着改变。
这里更多的技术是WPF资源ResourceDictionary。然后辅助于一些小技巧。

BlueTheme类说起:

    public class BlueTheme : ResourceDictionary
    
{
        
public BlueTheme()
        
{
            
this["background"= new SolidColorBrush(Colors.Blue);
        }

    }

这个类中this["background"]是比较费解的,因为BlueTheme派生于ResourceDictionary这个字典类,所以this["background"]等价于BlueTheme["background"]"background"key,而它的值是new SolidColorBrush(Colors.Blue)这个对象,从而我们可以这样使用BlueTheme类:

            BlueTheme blue = new BlueTheme();
            Object obj 
= blue["background"];
            Application.Current.Resources 
= obj;

这时obj是一个可以使用的SolidColorBrush类型的资源。

App中,建立应用程序级的themes变量,用来存储BlueTheme这些资源对象:
              static Dictionary<string, ResourceDictionary> themes;
              themes["Blue"] = new BlueTheme();

此时的themes["Blue"]等价于下列语句的rd对象:
            ResourceDictionary rd = new ResourceDictionary();
            rd.Add("background", new SolidColorBrush(Colors.Blue));
之后就可以在SetTheme方法中设置资源了。

            Application.Current.Resources = themes[theme];
这就添加了一个key"background",值为一个SolidColorBrush对象的资源。

主窗体和子窗体都使用如下语句来设置资源,因为在此之前App已经建立了"background"资源:
            this.SetResourceReference(Window.BackgroundProperty, "background");
这是一个动态资源,ResourceDictionary["background"]的改变,会使得应用了该资源的属性也跟着改变。

10LaunchDialogBox

This sample shows how to launch modal dialog boxes and message boxes.

这个例子讲的是主页面如何与对话框(dialog box)和消息框(message box)通信。
对于左边的对话框,并没有借助于Observer模式实现主从窗体建的通信,而是通过读写App.Current.Properties["UserData"]来传递值。
而右边的消息框则与传统方式一样,没有什么特别之处,只是详细的配置了MessagBox的各个属性。


点击左边按钮:

点击右边按钮:

注意到
ReturnEventArgs<T>派生自EventArgs

    public class ReturnEventArgs<T> : EventArgs
    
{
        
public ReturnEventArgs();
        
public ReturnEventArgs(T result);
        
public T Result getset; }
    }

默认构造函数使用于不需要传递参数的情形。

11NavigationServiceSample

This sample demonstrates using NavigationService to navigate to embedded and loose XAML content.

这个示例讲的是导航条NavigationService的使用。注意到其5个事件的使用(在Window加载的时候绑定方法)
Navigating
Navigated
NavigationProgress
NavigationStopped
LoadCompleted


其中只要发生导航动作(向前,向后,刷新,
Go按钮),都会先触发Navigating然后,只要每加载完毕,就会一直调用NavigationProgress加载结束,会调用Navigated最后是LoadCompleted

12NavWindowEvents

This sample shows how to handle the NavigationWindow events (C#, Extensible Application Markup Language (XAML)). It also displays the text equivalents of the arguments that are passed to the event handlers.

这个例子演示了NavigationWindow各种事件的用法。

LoadCompleted
Navigating
Navigated
NavigationProgress
NavigationStopped

在执行Navigate方法到一个新的Uri的时候,一般都会先后经历以下几个事件:Navigating——Navigated——LoadCompleted
对于导航到有若干Frame的页面,则是还要而外加上几套Navigated——LoadCompleted事件。
对于NavigationProgress方法,是在加载中不停地询问,加载了多少个字节,每次1024个字节,直到全部加载完成。这个方法在大块文字时才会激发,对于小于1024字节的文本,不会激发。

NavigationStopped
触发于以下语句,navWindow为导航窗口:
    navWindow.StopLoading();

注意,Hyperlink也有RequestNavigate事件——在设置了NavigateUri="Page1.xaml"的同时。在点击超链接时,也就激发了这个事件。

还有就是如何在
StackPanel中添加子控件,要使用它的Children属性:
            eventText.Children.Add(new TextBlock);//这里eventText是一个StackPanel
这个例子中左边显示的参数,是e的各个参数,如Content、Navigator和Uri,这个eNavigationEventArgs类型,携带着导航信息。

13NonRectangularWindowSample

This sample demonstrates how to create a non-rectangular window, which is configured using the Background, AllowsTransparency, and WindowStyle properties of the Window type.

这个例子是我目前见到的最酷的一个例子。

为了将Window的背景色设置为透明,需要配置以下三个属性,缺一不可:
     WindowStyle="None"
     AllowsTransparency="True"
     Background="Transparent"

14OnStartUp

This sample shows how to override the application object's OnStartingUp method in the application definition file to implement a custom startup procedure.

OnStartingUpApplication基类的虚方法,同样的方法还有
         OnActivated(EventArgs e);
         OnDeactivated(EventArgs e);
         OnExit(ExitEventArgs e);
         OnFragmentNavigation(FragmentNavigationEventArgs e);
         OnLoadCompleted(NavigationEventArgs e);
         OnNavigated(NavigationEventArgs e);
         OnNavigating(NavigatingCancelEventArgs e);
         OnNavigationFailed(NavigationFailedEventArgs e);
         OnNavigationProgress(NavigationProgressEventArgs e);
         OnNavigationStopped(NavigationEventArgs e);
         OnSessionEnding(SessionEndingCancelEventArgs e);

15OpenWindow

This example shows how to open a new window.

打开一个新Window的命令是 window1.Open();

16PageAPI

Use the Page tag to view and assign values to a variety of window properties.

Page中设定大小和Title可没有Window那么简单,WindowHeightWindowWidth,这两个属性在.NET2.0中仅用于设定Console窗体的大小,对WinForm无效。这里容易与WPF混淆的。.NET3.0中,这两个属性仅用于设定Page的大小——Window中没有,此时,在xaml中指定HeightWidth是没有用的。
    <Page Title="Page1" WindowHeight="300" WindowWidth="300">

       再说Title,要显示这个属性有点麻烦。可以直接在xaml中设置,但是不会显示。只有通过编程的方式,将其放在一个NavigationWindow中,并手动设置这个属性,才可以显示。

            NavigationWindow myWindow;
            myWindow 
= new NavigationWindow();
            myWindow.Navigate(
new Uri("Page1.xaml", UriKind.RelativeOrAbsolute));
            myWindow.Title 
= "123";
            myWindow.Show();

通过在App中指定StartupUri="Page1.xaml"打开初始页面;关闭Page时,也就是关

抱歉!评论已关闭.