1.如果根据用户的登录情况来动态的设置MainPage
如果本地有用户的信息,则直接登录到主界面MainPage
如果没有,则需要进入到LoginPage,并且登录成功后进入MainPage,并且移除LoginPage,否则会出现按返回键重新右MainPage进入LoginPage的情况,显然这不符合常规
App.xaml.cs:
protected static Page GetMainPage() { Page mainPage = null; if (AppParams.IsLogin) { mainPage = new MainPage (); } else { mainPage = new LoginPage (); } return mainPage; }
LoginPage.xaml.cs:
App.Current.MainPage.Navigation.PopModalAsync(); App.Current.MainPage=new MainPage();
MainPage是一个MasterDetailPage,是将Detail设置为Detail=new NavigationPage(new DetailPage);
如果你的主页是一个常规的Contentpage,此时上面的第二段话应该是:
App.Current.MainPage.Navigation.PopModalAsync(); App.Current.MainPage=new NavigationPage(new MainPage());
当然,你如果不需要Navigation,当然可以不用这样写了
2.主线程与异步线程注意的地方
今天发现一个很奇怪的问题,本来就下面这段代码在主线程中执行,为了加快速度,将之移到异步线程,然后发现功能不对了
var curPage = FormsCommonUtils.GetCurrentPage (); if (curPage != null&&curPage.ToolbarItems!=null) { for (int i=0;i<curPage.ToolbarItems.Count;i++) { if (curPage.ToolbarItems[i].Text == Strings.ToolbarItem_CacheList) { //不能放在非主线程中执行,执行的时候,i已经又++了,此时并不会移除item Device.BeginInvokeOnMainThread (()=>{ try { curPage.ToolbarItems.RemoveAt(i); } catch (Exception ex) { } }); } }
就是移除ToolbarItem,发现放在异步线程中时,
curPage.ToolbarItems.RemoveAt(i); //i=3
说明执行这段代码的时候,i又在后面判断了一次
结论:涉及到for循环的时候,要将整个for循环放在主线程中执行,不要单独将{}里面的代码放在主线程中执行
3.最蛋疼的控件Picker
Picker可谓forms里面最垃圾的一个控件,本来可以做成数据绑定的,第三方都实现了,官方就是没有实现
今天又遇到一个问题,我通过双向绑定Picker的SelectedIndex来改变Picker的选中状态,发现这个改变在构造函数中是无效的,ViewAppearing中才有效,譬如你在构造函数中设置了Picker的SelectedIndex为1(此时已给Picker设置了Items),最后实际的效果还是初始状态:
猜想一:
设置Picker的Items这个过程需要花费时间,你在复制SelectedIndex为1的时候,Items的设置还没完成
猜想二:
待添加...
Picker为我自定义可绑定的BoundPicker,原生的测试的确可以,不会发生上面:
for (int i = 0; i < 5; i++) { myPicker.Items.Add (i+""); } myPicker.SelectedIndex = 2;
4.禁用Page里面的所有控件
1.实际测试不管是设置Page,获取Page.Content第一级元素的IsEnable为false都是没有效果的,布局里面的控件依旧有效
2.想用Style来设置所有元素的IsEnabled属性,发现Style的TargetType不支持继承类型的,譬如你设置TargteType=View,并不会改变所有控件的属性(所有控件都是继承子View),所以如果想到Style来完成,必须搞清楚Page里面到底有哪些种类的控件,然后针对这个种类的逐个添加Style
3.最简单的方法,如果主布局是一个RelativeLayout或者Grid,可以在最上面添加一个透明的布局,这样就完全屏蔽了下面的控件
4.像Android那样,从Page的对象树,依次向下找到所有的控件,每个控件逐一设置
5.Binding遇到的奇怪的问题
其它不重要,重要的是这坑爹的问题没有报错,直接就退出了,什么日志都没有
<Entry Grid.Row="3" Grid.Column="1" Text="{Binding inputunitname}" />
private string _inputunitname; /// <summary> /// /// </summary> public string inputunitname{ get{ return _inputunitname;} set{ SetProperty (ref _inputunitname, value);} }
直接赋值对象,inputunitname为对象里面的一个属性,如果这样写,直接退出,不是FC,什么错误都没有
所以,如果大家只是使用Entry显示数据的时候,注意设置BindingMode为OneWay,不要设置NotifyPropertyChanged(""),可能就会碰到我这个问题,还是修改xaml多次试出来问题的根源的
好吧,实际上model里面还有其它的数据也是跟inputunitname一样的格式,但是就是不报错,算我倒霉,犯了忌讳了
6.Converter不触发
Title="{Binding DataList.Count,Converter={StaticResource ListCountTitleConverter},ConverterParameter='巡检任务'}"
这种情况,如果DataList==null时,Converter是不会被触发的,最好是将Path设为DataList而不是DataList.Count
7.像View和Control这种出现无法识别
因为在Xaml文件中的class里面,有View作为命名空间,与类冲突了,将命名空间不使用View就行了
8.StringFormat导致的卡死的问题
Forms版本:2.3.1
当传过去的Value为null的时候,此时设置了StringFormat,会导致界面卡死,譬如{Binding value,StringFormat='{0}米'}
这种情况会在Entry中出现,Entry的默认值是TwoWay,如果设置Mode=OneWay,该现象会消失
9.StackLayout中前面元素的高度与后面元素的高度一致
10.左右靠边对其
这个一个很简单的问题,但是有时候在某些特定情况下,会出现一些情况
<StackLayout Orientation="Horizontal" Grid.Row="4" Grid.ColumnSpan="3" > <Label Text="11344asdasdasdasdsadsadsadsaddsd" LineBreakMode="TailTruncation" TextColor="Red" HorizontalOptions="StartAndExpand"/> <Label Grid.Column="1" Text="右边" TextColor="Green"/> </StackLayout>
//如果左边的文字比较短,一切是没问题的 //但是如果左边的问题过长,会将右边的问题换行,或者向左移动
那将右边的Label的LineBreakMode设为NoWrap,是不是会解决这种情况呢?
//依旧不会,会直接将Label挤出屏幕
正确的方法:
<Grid Orientation="Horizontal" Grid.Row="3" Grid.ColumnSpan="3"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <Label Text="11344asdasdasdasdsadsadsadsaddsdsddsdsdsdsddsdsada" LineBreakMode="TailTruncation" TextColor="Red" HorizontalOptions="StartAndExpand"/> <Label Grid.Column="1" Text="右边" TextColor="Green"/> </Grid>
//即使左边的文字过长,也不会出现上面的情况
11.webView支持手势放大缩小
iOS: public class CustomWebViewRenderer : WebViewRenderer { protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); var view = (UIWebView)NativeView; view.ScrollView.ScrollEnabled = true; view.ScalesPageToFit = true; } } Android: protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e) { base.OnElementChanged(e); var settings = Control.Settings; settings.JavaScriptEnabled = true; settings.BuiltInZoomControls = true; settings.UseWideViewPort = true; settings.SetSupportZoom(true); }