给 Xamarin.Form For Windows Phone APP 加个漂亮的 "头"
Windows Phone 是那个1%, 我也是那个1%, 不喜勿喷.
WP 向来给 android / ios 的粉们一个最直观的印象: 丑.
其实"丑"这个东西会一直下去,而且是个解不开的死循环.
WP 下, 做的华丽的, 目前我用过的只有少数几个, 网易云音乐 和 智机社区, 做的漂亮而且流畅, 其它的只能用渣渣来形容.




Xamarin.Form 的 APP 在 Android 和 IOS 下默认都会有一个"头", 用于显示页面名称和导航按钮.
在 WP 下却没有, 像这样:

Xamarin.Form 在 WP 的 MainPage.xaml.cs 中这样定义:
public partial class MainPage : FormsApplicationPage{
...
public MainPage() {
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape;
global::Xamarin.Forms.Forms.Init();
LoadApplication(new LBC.Mobi.App());
}
FormsApplicationPage.LoadApplication 方法的定义:
protected void LoadApplication(Xamarin.Forms.Application application)
{
Xamarin.Forms.Application.Current = application;
application.PropertyChanged += new PropertyChangedEventHandler(this.ApplicationOnPropertyChanged);
this.application = application;
application.SendStart();
this.SetMainPage();
}
private void SetMainPage()
{
if (this.platform == null)
this.platform = new Platform((PhoneApplicationPage) this);
this.platform.SetPage(this.application.MainPage);
if (this.Content == this.platform)
return;
this.Content = (UIElement) this.platform;
}
这样一个调用链:
LoadApplication -> SetMainPage -> 直接给整个页面的 Content 赋值.
所以, 无论你在 MainPage.xaml 中写什么内容, 最终都是无法显示的.
为了达成目的, 我们需要修改 SetMainPage 方法 , 使 this.platform 只作为 MainPage 的一部分, 而不是整个 Content.
但是反编译一下, 可以看到 Xamarin.Form 的封装很蛋疼, 很多都是 internal , private, 不带 virtual, 所以, 通过正常手段是无法对 Xamarin.Form 进行扩展的.

还好, Xamarin 对反射支持的很到位, 无法正常通过继承/重写来实现, 我们照样可以用反射来完成它.
1, 在 MainPage.xaml.cs 中新增方法 LoadApplication:
new protected void LoadApplication(Xamarin.Forms.Application application) {
//Xamarin.Forms.Application.Current = application;
typeof(Xamarin.Forms.Application).GetProperty("Current", BindingFlags.Static | BindingFlags.Public)
.SetValue(Xamarin.Forms.Application.Current, application);
application.PropertyChanged += new PropertyChangedEventHandler(this.ApplicationOnPropertyChanged);
typeof(FormsApplicationPage).GetField("application", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, application);
//application.SendStart();
application.GetType().GetMethod("SendStart", BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(application, null);
this.SetMainPage();
17 var mp = (Xamarin.Forms.NavigationPage)application.MainPage;
18 mp.PropertyChanged += MainPage_PropertyChanged;
19 this.Title = mp.Title;
}
为了能显示当前页的标题, 我在上面的方法中加了一段(红色标注), 实际中, 你的 application.MainPage 可能不是 NavigationPage, 需要自行修改.
2,
void MainPage_PropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName.Equals("CurrentPage")) {
this.Title = ((Xamarin.Forms.NavigationPage)sender).CurrentPage.Title;
this.PropertyChanged(this, new PropertyChangedEventArgs("Title"));
}
}
3, 在 MainPage.xaml.cs 中添加 SetMainPage :
private void SetMainPage() {
if (this.Platform == null) {
this.Platform = new Platform((PhoneApplicationPage)this);
}
this.Platform.SetPage(Xamarin.Forms.Application.Current.MainPage);
if (this.mainBody.Content != null && this.mainBody.Content.Equals(this.Platform))
return;
this.mainBody.Content = (UIElement)this.Platform;
}
4, 修改 MainPage.xaml
<winPhone:FormsApplicationPage
x:Class="Discuz.WinPhone.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winPhone="clr-namespace:Xamarin.Forms.Platform.WinPhone;assembly=Xamarin.Forms.Platform.WP8"
xmlns:local="clr-namespace:Discuz.WinPhone"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
shell:SystemTray.Opacity="0"
Background="#1e5263"
>
<!--shell:SystemTray.BackgroundColor="#2ba9d3"-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="15" /><!-- for SystemTray -->
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<local:TilePanel TileWidth="5" TileHeight="5" Height="65" Grid.Row="0" Grid.RowSpan="2">
<local:TilePanel.Image>
<ImageBrush ImageSource="texture.png" />
</local:TilePanel.Image>
</local:TilePanel>
<StackPanel Orientation="Horizontal" Margin="10,0" Grid.Row="1" VerticalAlignment="Center">
<Image Source="icon.png" Width="40" Height="40" Margin="0,0,10,0" />
<TextBlock Text="{Binding Title}" VerticalAlignment="Center" />
</StackPanel>
<ContentPresenter x:Name="mainBody" Grid.Row="2" />
</Grid>
</winPhone:FormsApplicationPage>
好啦, 一个带标题的 XF For WP 的 APP 改造完了.
最终效果:


具体参见:
https://github.com/gruan01/Discuz.Mobi/tree/master/Discuz/Discuz.WinPhone
--------------------
OK, 完
给 Xamarin.Form For Windows Phone APP 加个漂亮的 "头"的更多相关文章
- FlipView For Xamarin.Form 之 IOS
之前写过两篇博文 是关于 Android 和 Windows Phone 下的 FlipView 的实现. 上上周,有个印度佬通过 GitHub 找到我, 问我有没有打算个 ios 端的,还说比较了相 ...
- Xamarin.Form 实例: Discuz BBS 客户端 源码分享
感谢台风, 这个十一长假让我好好的休息了一回, 睡觉到腰酸背疼, 看电影看到眼发红. 今天最后一天, 不敢出去逛, 不知道哪会还会下暴雨... 嗯嗯..这个项目其实在十一之前就开始了, 工作无聊,没有 ...
- Visual Studio + C# + Xamarin = iOS/Android/Windows Apps
Visual Studio 跨平台開發實戰 (1) -- Hello Xamarin! 前言 應用程式發展的腳步,從來沒有停過.從早期的 Windows 應用程式, 到網路時代的 web 應用程式,再 ...
- Windows Phone App的dump 文件分析
前言 我们在发布了自己的App以后,Windows Phone的Error Report机制会帮助我们收集程序的崩溃信息并发送到微软的服务器上,这可以辅助开发者提高App的稳定性. 那么如何利用这些d ...
- [Windows Phone] APP上架,遇到错误2001的解决方案。(Error:2001)
[Windows Phone] APP上架,遇到错误2001的解决方案.(Error:2001) 问题情景 最近在开始玩Windows Phone的开发,开发的过程中虽然有点小挫折,但是参考网络许多前 ...
- Xamarin Android Fragment的两种加载方式
android Fragment的重点: 3.0版本后引入,即minSdk要大于11 Fragment需要嵌套在Activity中使用,当然也可以嵌套到另外一个Fragment中,但这个被嵌套的Fra ...
- Xamarin.Form怎么调用原生方法
---恢复内容开始--- Xamarin.Form怎么调用原生包 今天我想和大家分享的是有关Xamarin如何调用安卓的原生代码,下面的例子以大家可能会经常用到的微信WX方法的调用. 首先我们新建一个 ...
- Xamarin.Form与Xamarin.Android或Xamarin.IOS的区别简述
Xamarin.Form与Xamarin.Android或Xamarin.IOS的区别简述: 可能刚刚接触Xamarin的人来说,对于这个概念比较的模糊,认为这说的不都是同一个东西吗?事实并不是这样的 ...
- 在桌面程序上和Metro/Modern/Windows store app的交互(相互打开,配置读取)
这个标题真是取得我都觉得蛋疼..微软改名狂魔搞得我都不知道要叫哪个好.. 这边记录一下自己的桌面程序跟windows store app交互的过程. 由于某些原因,微软的商店应用的安全沙箱导致很多事情 ...
随机推荐
- 【体系结构】Oracle参数介绍
[体系结构]Oracle参数介绍 1 BLOG文档结构图 2 前言部分 2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩ ...
- GitHub中wiki的Markdown编辑方法!!
Hello MarkDown!正常的文本 一级大标题用一个#号 一级中等标题用两个#号 一级小标题用三个#号(一次类推,一共有6级标题) 下面是无序列表 无序标题1-只需要在标题前面加上*号就可以了或 ...
- 【OpenCV】全景拼接
从OpenCV3.0正式版开始,features2d中的一些接口,搬到附加库xfeatures2d中了,其中就有SIFT.SURF的特征检测方法,但是正常下载安装OpenCV并不包含附加库,因为附加库 ...
- 合工大 OJ 1322 窗口
窗口 Description 在某图形操作系统中,有N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域.窗口的边界上的点也属于该窗口.窗口之间有层次的区别,在多于一个窗口重叠的区域里, ...
- [转载]ExtJs4 笔记(8) Ext.slider 滚轴控件、 Ext.ProgressBar 进度条控件、 Ext.Editor 编辑控件
作者:李盼(Lipan)出处:[Lipan] (http://www.cnblogs.com/lipan/)版权声明:本文的版权归作者与博客园共有.转载时须注明本文的详细链接,否则作者将保留追究其法律 ...
- 如何显示隐藏的Administrator账户
在Windows XP中,Administrator帐户是终极管理员,如果你创建了其他管理员帐户,那么该帐户就会从欢迎屏幕上被隐藏.这里需要注意的是,仅仅是从欢迎屏幕上被隐藏,该帐户仍然存在. 如 ...
- 权限框架 - shiro 授权demo
之前说了权限认证,其实也就是登录验证身份 这次来说说shiro的授权 shiro可以针对角色授权,或者访问资源授权 两者都行,但是在如今的复杂系统中,当然使用后者,如果你是小系统或者私活的话,前者即可 ...
- 第20章 DLL高级技术(2)
20.3 延迟载入DLL 20.3.1延迟载入的目的 (1)如果应用程序使用了多个DLL,那么它的初始化可能比慢,因为加载程序要将所有必需的DLL映射到进程的地址空间.→利用延迟加载可将载入过程延伸到 ...
- Unity的物理材质
Physic Materials资源包 在Unity中的项目导入Unity自带的资源包 Physic Materials,自带的资源包有不同种类的物理材质: Bouncy:有弹性的 Ice:结冰 Me ...
- Linux下squid代理缓存服务环境部署
代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息. Squid是一个缓存Internet 数据的软件,其接收用户的下载申请,并自动处理所下载的数据.当一个用户想要下载 ...