【问题标题】:Xamarin Forms Switch NightmareXamarin 表单切换噩梦
【发布时间】:2020-01-15 17:36:07
【问题描述】:

我不敢相信我花了一天的时间来尝试让它工作!我上个月开始在 Xamarin.Forms 中进行开发,并且大部分情况下进展非常顺利。我的背景是 ASP.Net MVC 和 Windows Forms,所以 MVVM 概念对我来说是新的。

我遇到的问题非常令人沮丧,而且看起来真的很愚蠢。我想这可能是我的实现,可能是因为我没有使用 MVVM,而是在后面的代码中执行所有绑定?我有一个包含搜索框和 ListView 控件的页面。 ListView 中的每个项目都相当简单......它只包含几个标签和一个开关。每次有人执行搜索时都会绑定 ListView。我遇到的问题是,每次有人执行搜索时,它都会刷新模型,每次都绑定到......这反过来又会触发 Switches Toggle 事件。在切换事件中,我有代码可以在值更改时更新数据库,所以我不希望每次模型更改时都会触发它。这是非常令人沮丧的,因为似乎没有点击事件。请参阅下面的 Xaml 和我正在使用的方法:

    public async void SearchItems()
    {
        PageLoaded = false;
        if(string.IsNullOrEmpty(this.txtSearch.Text)) { return; }
        this.LoadSearch.IsRunning = true;
        // Populate Locations For Item
        string ItemType = HttpUtility.UrlEncode(this.SelectItemType.SelectedItem.ToString());
        string Search = HttpUtility.UrlEncode(this.txtSearch.Text.ToLower());
        string url = string.Format("https://test.com/api/LocationsSearch?itemType={0}&search={1}", ItemType, Search);
        LocationsList = new List<Locations>();
        var json = await func.GetIBApi(url);
        LocationsList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Locations>>(json);
        this.ItemsList.ItemsSource = LocationsList;
        this.LoadSearch.IsRunning = false;
        PageLoaded = true;
    }

切换事件:

        private async void Switch_Toggled(object sender, ToggledEventArgs e)
        {
            try
            {
                if (PageLoaded)
                {
                    bool isPrimary = e.Value;
                    ViewCell cell = (sender as Switch).Parent.Parent.Parent as ViewCell;
                    var location = cell.BindingContext as Locations;

                    string display = "";
                    if (isPrimary)
                    {
                        display = "Are you sure you want to make this the 'Primary Location'?";
                    }
                    else
                    {
                        display = "Are you sure you want to unset this as the 'Primary Location'? Note: Make sure you set another location as the 'Primary' on this PartNumber!";
                    }

                    var result = await App.Current.MainPage.DisplayAlert("Primary Change Confirmation", display, "Yes", "No");
                    if (result)
                    {
                        string url = string.Format("https://test.com/api/LocationsSearch?partNumber={0}&location={1}&isPrimary={2}", location.ID, location.Location, isPrimary);
                        var json = await func.PostIBApi(url);
                        await Navigation.PopModalAsync();
                    }
                }
            }
            catch (Exception e2)
            {

            }
        }

XAML:

    <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="IBMobile.Views.LocationsPage"
             xmlns:local2="clr-namespace:FontAwesome"
             Visual="Material">
    <ContentPage.IconImageSource>
        <FontImageSource FontFamily="{StaticResource FontAwesomeSolid}" Glyph="{x:Static local2:IconFont.MapMarkerAlt}" />
    </ContentPage.IconImageSource>
    <ContentPage.Content>
        <StackLayout Padding="25">
            <Picker  x:Name="SelectItemType" SelectedIndexChanged="SelectItemType_SelectedIndexChanged" />
            <SearchBar x:Name="txtSearch" SearchButtonPressed="TxtSearch_SearchButtonPressed"  Placeholder="Search..." FontSize="Title"></SearchBar>
            <ActivityIndicator Color="#007D5D" IsRunning="false" x:Name="LoadSearch"  HorizontalOptions="Center" />
            <ListView x:Name="ItemsList" ItemTapped="ItemsList_ItemTapped"  HasUnevenRows="True" BackgroundColor="White">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout VerticalOptions="FillAndExpand">
                                <Grid VerticalOptions="FillAndExpand" Padding="0">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="3*"></ColumnDefinition>
                                        <ColumnDefinition Width="3*"></ColumnDefinition>
                                        <ColumnDefinition Width="1*"></ColumnDefinition>
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"></RowDefinition>
                                        <RowDefinition Height="Auto"></RowDefinition>
                                        <RowDefinition Height="Auto"></RowDefinition>
                                    </Grid.RowDefinitions>

                                    <Label TextColor="#007D5D" Text="{Binding ViewID}" FontSize="Title" VerticalTextAlignment="Center" Grid.Column="0" Grid.Row="0"></Label>
                                    <Label TextColor="#007D5D" Text="{Binding Location}" FontSize="Title" VerticalTextAlignment="Center" Grid.Column="1" Grid.Row="0"></Label>
                                    <Label Text="Primary" Grid.Column="2" Grid.Row="0"></Label>
                                    <Switch IsToggled="{Binding IsPrimary}" x:Name="Toggle1" ThumbColor="#007D5D" Grid.Column="2" Grid.Row="1" Toggled="Switch_Toggled"/>
                                    <Label  Text="{Binding Description}"  Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"></Label>
                                    <Label  Text="{Binding Message}"  Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="3" FontSize="Small" TextColor="Red"></Label>
                                </Grid>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

【问题讨论】:

  • 缺少部分代码,IsPrimary 设置在哪里?
  • @NickKovalsky 查看已修改,谢谢。
  • 添加PageLoaded后,在搜索动作中仍然触发Toggle事件?不应该。
  • 您能否提供一个可以重现问题的样本?

标签: c# xamarin.forms


【解决方案1】:
    if (PageLoaded)
                    {
                        //entered handler
                        bool isPrimary = e.Value; //we are invoking the handler again from inside itsself
                                                  // all the mess comes from this

使用另一个锁:

 if (PageLoaded && !_internal)
                        {
                            //entered handler
                            _internal=true;
                            bool isPrimary = e.Value;
                            _internal=false;

【讨论】:

  • 谢谢...我尝试了类似的东西,我知道这不是很明显,因为我错过了切换事件。在我的代码中,属性标志称为 PageLoaded,我在 Search 方法的开始和结束时设置它。有什么想法吗?
  • 这个想法是,当在 PageLoaded=true; 时设置 IsPrimary 时,你的麻烦就来了。您基本上是从内部调用处理程序两次
  • 不幸的是,这给了我相同的结果。事实上,每次我执行搜索时它都会触发事件。
  • 看你的代码,你的意思是当PageLoaded==false时它执行if (PageLoaded)里面的代码,对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 2010-12-21
  • 2020-03-14
  • 2010-11-13
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多