(持续更新)Xamarin.Forms之常见的问题

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);
        }
原文地址:https://www.cnblogs.com/yz1311/p/5233287.html