WPFWPFWPFWPF学习笔记目录WPF学习笔记.................................................................................................................................1Application................................................................................................................................1Dispatcher................................................................................................................................3Navigation................................................................................................................................5XAML.........................................................................................................................................9DependencyProperty............................................................................................................15RoutedEvent..........................................................................................................................20Resource.................................................................................................................................24Binding....................................................................................................................................31Silverlight-Hello,World!................................................................................................................68ApplicationApplicationApplicationApplication和WinForm类似,WPF同样需要一个Application来统领一些全局的行为和操作,并且每个Domain中只能有一个Application实例存在。和WinForm不同的是WPFApplication默认由两部分组成:App.xaml和App.xaml.cs,这有点类似于DelphiForm,将定义和行为代码相分离。当然,WebForm也采用了类似的方式。XAML从严格意义上说并不是一个纯粹的XML格式文件,它更像是一种DSL,它的所有定义都直接映射成某些代码,只不过具体的翻译工作由编译器完成而已。下面是一个简单的App定义。publicpartialclassApp:Application{}当你在自动生成的Project代码中看到paritialparitialparitialparitial时,应该下意识去找找Thiscodewasgeneratedbyatool.……不过这次自动生成的代码存放位置更加古怪——obj\Debug\App.g.csobj\Debug\App.g.csobj\Debug\App.g.csobj\Debug\App.g.cs。publicpartialclassApp:System.Windows.Application{[DebuggerNonUserCode]publicvoidInitializeComponent(){this.StartupUri=newSystem.Uri(Window1.xaml,System.UriKind.Relative);}[STAThread][DebuggerNonUserCode]publicstaticvoidMain(){Appapp=newApp();app.InitializeComponent();app.Run();}}App.StartupUri用于设置MainWindow,App.Run()启动消息循环。当然,还有那个STAThread,这意味着WPF依旧使用一个UIThread来处理UIMessage。我们完全可以舍弃自动生成的代码,自己手工写一个App。publicclassApp:Application{[STAThread]privatestaticvoidMain(){varapp=newApp();varwindow=newWindow{Title=WPF};app.Run(window);}}Application提供了一些实用的属性和方法。CurrentCurrentCurrentCurrent:获取Domain中默认的Application实例。MainWindowMainWindowMainWindowMainWindow:获取主窗口实例。WindowsWindowsWindowsWindows:获取所有被实例化的Window实例。ShutdownModeShutdownModeShutdownModeShutdownMode:指定Application.Shutdown方式,包括主窗体关闭,最后一个窗口关闭,以及手工调用Shutdown()。PropertiesPropertiesPropertiesProperties:一个线程安全的全局字典,可用来存储一个公共信息。ShutdownShutdownShutdownShutdown:该方法终止ApplicationProcess,可向操作系统返回一个退出码。我们依然可以使用Mutex来阻止运行多个实例。privatevoidApplication_Startup(objectsender,StartupEventArgse){varcreatedNew=false;varname=Assembly.GetEntryAssembly().FullName;newMutex(true,name,outcreatedNew);if(!createdNew){MessageBox.Show(Thereisalreadyaninstancerunning,Exit!);Application.Current.Shutdown();}}当然也可以用Windows属性判断窗体是否已经存在。privatevoidbutton1_Click(objectsender,RoutedEventArgse){varwindow2=Application.Current.Windows.OfTypeWindow().FirstOrDefault(w=wisWindow2);if(window2==null)window2=newWindow2();window2.Show();window2.Activate();}---------------------无聊的分割线--------------------迟到的笔记总算开始了,算是为Silverlight做准备吧。DispatcherDispatcherDispatcherDispatcherWPF使用一个专用的UI线程来完成界面的操作和更新,这个线程会关联一个唯一的DispatcherDispatcherDispatcherDispatcher对象,用于调度按优先顺序排列的工作项队列。Application.Run()实际上就是对Dispatcher.Run()的间接调用。Dispatcher通过循环来处理工作项队列,这个循环通常被成为帧(DispatcherFrame)。Dispatcher.Run()创建并启动这个帧,这也是Application.Run()启动消息循环的最终途径。publicsealedclassDispatcher{[SecurityCritical,UIPermission(SecurityAction.LinkDemand,Unrestricted=true)]publicstaticvoidRun(){PushFrame(newDispatcherFrame());}}DispatcherFrame可以嵌套,并通过检查Continue属性来决定循环是否继续。我们可以通过调用Dispatcher.ExitAllFrames()来终止所有的帧循环,当然这种编程方式并不可取,可能会造成一些意外出现。与Dispatcher调度对象想对应的就是DispatcherObjectDispatcherObjectDispatcherObjectDispatcherObject,在WPF中绝大部分控件都继承自DispatcherObject,甚至包括Application。这些继承自DispatcherObject的对象具有线程关联特征,也就意味着只有创建这些对象实例,且包含了Dispatcher的线程(通常指默认UI线程)才能直接对其进行更新操作。当我们尝试从一个非UI线程更新一个标签,会看到一个如下的异常。privatevoidbutton1_Click(objectsender,RoutedEventArgse){newThread(()=this.label1.Content=DateTime.Now.ToString()).Start();}按照DispatcherObject的限制原则,我们改用Window.Dispatcher.Invoke()即可顺利完成这个更新操作。privatevoidbutton1_Click(objectsender,RoutedEventArgse){newThread(()={this.Dispatcher.Invoke(DispatcherPriority.Normal,newAction(()=this.label1.Content=DateTime.Now.ToString()));}).Start();}如果在其他项目(比如类库)中,我们可以用Application.Current.Dispatcher.Invoke(...)完成同样的操作,它们都指向UIThreadDispatcher这个唯一对象。Dispatcher还提供了BeginInvoke这个异步版本。privatevoidbutton1_Click(objectsender,RoutedEventArgse){newThread(()={Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,newAction(()={Thread.Sleep(3000);thi