2015年1月26日星期一

博客园客户端UAP开发随笔 – 让自己的App连接世界(2):WinRT中的内置分享 - MS-UAP

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
博客园客户端UAP开发随笔 � 让自己的App连接世界(2):WinRT中的内置分享 - MS-UAP  阅读原文»

看到一篇眼前一亮的博文,是不是有一种希望其他小伙伴都能看到的感觉呢?有没有一种“不转不是程序员”的冲动呢?在 PC 浏览器上看到还好办,直接网址复制,另一边 IM 上就发过去了,但是如果是 App 中的内容,就没这么方便了,总不能那边 IM 上喊话:“隔壁老王,博客园上有篇叫‘博客园客户端(Universal App)开发随笔 – 为应用插上分享的翅膀’的博文超好看,要不你也瞅瞅?”。隔壁老王再去搜索就太麻烦了。可能你会说了,嗨,直接分享不就完了么。嗯,没错,就是分享功能。那么如何把分享功能引入我们的 App 中呢?往下看。

Universal App 中 Windows / Windows Phone 之间分享的异同

既然是 Universal App,那自然是共享一套分享的代码啦。但是在这两个之间还是有点不一样的。区别在于,Windows 版由于有 Charm Bar 这个系统级的菜单,而这菜单里是自带分享入口的,所以 Windows 版只需要提前准备好需要分享的内容,而不需要再提供另外的分享入口。而 Windows Phone 没有这个入口,所以除了需要准备好内容,还需要通过菜单或按钮的形式,显式提供一个分享的入口。

image

不过随着 Windows 10 的发布,Charm Bar 的寿命也走到了尽头,在之前的 Technical Preview 中还是偶尔可以(误触)调出 Charm Bar 的,但是在刚刚发布的 Costumer Preview,我们应该就见不到 Charm Bar 的身影了,所有它提供的入口,都被移到了下图所示的位置:

image

这一点倒是不难理解,因为所有的 App 都可以窗口化了,右滑调出 Charm Bar 的方法已经不好用,所以单独提供一个入口。不过不得不说,这个入口的尺寸不是很适合点击,而且呼出的菜单更是容易误触,尤其是在 Surface Pro 的高分屏上。这个改动,也使得原来上/下滑呼出 App Commands 的操作需要两步才能完成,极为繁琐。我们也因此不得不在新版的博客园中添加了 App Commands 的快捷入口。

另外,Windows 默认提供了两种分享的方式,一是使用开发者提供的信息,二是直接分享当前屏幕截图。而截至到目前的 Windows Phone Technical Preview 中,也是只有一种分享方式的,没有截屏的选项。在 Windows Phone 中,我们还需要手动添加一个入口,如下图所示。

创建分享(以 Text 举例)

好了,我们以博客园的博文分享举例,来介绍一下如何创建一个分享。

在动手之前,我们要先在脑海里想一下需要分享的内容。例如,博客园我们需要分享如下格式的信息(分割线以内):

--------------

标题:博文标题

作者:博文作者

摘要:博文摘要

博文链接

--------------

思路是这样的,我们先创建一个字符串,包含以上信息,然后加入注册到分享内容,最后显式或系统调用出分享入口,进行分享。

具体实现如下:

首先添加引用:

using Windows.ApplicationModel.DataTransfer;

然后创建一个叫RegisterForShare的方法,将需要分享的内容注册到分享区:

private void RegisterForShare()
{
DataTransferManager dataTransferManager
= DataTransferManager.GetForCurrentView();
dataTransferManager.DataRequested
+= new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.ShareTextHandler);
}

在这个方法里,我们创建了一个 DataTransferManager,并让他在 DataRequested 事件时出发 ShareTextHandler 方法:

private void ShareTextHandler(DataTransferManager sender, DataRequestedEventArgs e)
{
DataRequest request
= e.Request;
request.Data.Properties.Title
= loader.GetString("ShareTitlePrefixText") + this.post.Title;
request.Data.Properties.Description
= this.post.Summary;
string summaryText = (this.post.Author != null ? loader.GetString("ShareContentAuthor") + this.post.Author.Name : "") + "\n"
+ loader.GetString("ShareContentSummary")
+ (this.post.Summary.Length > 50 ? this.post.Summary.Substring(0, 50) : this.post.Summary) + "\n"
+ this.post.Link.Href;
request.Data.SetText(summaryText);
}

接下来实现这个方法,创建一个 request,并完善其中的内容,其中 request.Data.Properties.Title 是会显示在分享的标题部分的内容,例如如果是邮件分享,那么邮件标题就是 request.Data.Properties.Title,如果 Onenote 分享,那么 note 的标题也会是 request.Data.Properties.Title。request.Data.Properties.Description 不是必选项,仅仅是个备注参考,不会在分享时显示出来。最后的 request.Data.SetText(summaryText); 将其余需要分享的内容设置好。这样,我们的需要分享的内容就像之前想的一样都已经填写进去了。

接下来要做的,是先调用 RegisterForShare 方法,这个过程可以在构造函数中完成。

分享入口

如果是 Windows,那么在构造函数调用了 RegisterForShare 方法以后,就已经可以直接分享了,入口就是之前提到过的 Charm Bar 或 菜单:

image

右边的下拉菜单,可以选择分享内容或截屏:

image

我们选择邮件分享内容

image

就可以发送了。

如果是 Windows Phone,那么我们还需要多做一步。

创建一个菜单的入口:

<AppBarButton x:Name="btn_Share" x:Uid="ShareBlogButton" Label="分享博文" Click="btn_Share_Click" Icon="ReShare"/>

然后在点击的方法中,显式调用分享入口:

private void btn_Share_Click(object sender, RoutedEventArgs e)
{
Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareU
ASP.NET MVC路由解析 - Sinte-Beuve  阅读原文»

继续往下看《ASP.NET MVC5框架揭秘》。

ASP.NET系统通过注册路由和现有的物理文件路径发生映射。而对于ASP.NET MVC来说,请求的是某个Controller中的具体的Action方法。

路由注册和忽略的方法与ASP.NET不同,位于RouteCollectionExtensions中。

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
  name:
"Default",
  url:
"{controller}/{action}/{id}",
  defaults:
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
  );
UrlParameter.Optional表示只有请求的URL真正包含具体变量值时RouteData里才会有相应的变量存储。
Area路由映射
场景:假设在Controller下有一个文件夹api,里面包含了用来调用的api。而且api目录下的Controller可能包含和Controller目录下相同命名的Controller。
这个时候可以通过AreaRegisteration来实现。AreaRegisteration是一个抽象类。
public abstract class AreaRegistration
{
protected AreaRegistration();
public abstract string AreaName { get; }
public static void RegisterAllAreas();
public static void RegisterAllAreas(object state);
public abstract void RegisterArea(AreaRegistrationContext context);
}

建一个ApiAreaRegisteration,实现抽象方法和属性。

public class ApiAreaRegisteration :AreaRegistration
{
     //返回一个Area名
public override string AreaName
{
get { return "api"; }
}
  
public override void RegisterArea(AreaRegistrationContext context)
{
object defaults = new
{
Controller
= "utility",
Action
= "Add",
num
= 1
};
context.MapRoute(
"apidefault","api/{controller}/{action}/{num}",defaults,new string[]{"MvcTest.Controllers.api"});
}
}

在global.asax里注册

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
}
AreaRegistrationContext 是对应的上下文包含AreaName、Routes等信息和一系列注册路由的方法。
调用
AreaRegistration.RegisterAllAreas()静态方法后,会反射创建ApiAreaRegisteration 对象,调用RegisterArea()方法实现路由注册。

注:本博文大多数内容来自《ASP.NET MVC5框架揭秘》中,只是做内容的梳理和总结。


本文链接:ASP.NET MVC路由解析,转载请注明。

阅读更多内容

没有评论:

发表评论