简体   繁体   中英

Trying to close a ViewCell.ContextAction on button click in Xamarin

在此处输入图片说明

Currently its set in the listview that if the user swipes left on an item in the list it will then bring up two buttons (favorite and completed, shown above) the user could press. The buttons do what they are supposed to do. The only thing is that I think it is hard for the users to tell their button pressed actually worked so I was hoping I could close the ContextAction after they press the button. Currently, the only way they can get the listview to go back to normal, or close that Context Action is to swipe left.

I tried attaching ax:Name property to the ContextActions part of the cell to see if there was an IsVisible or Close property but that name wasn't being found in my code behind. I'm also wondering if there is a way I could mimic a swipe left action in my OnClick events.

Any idea how I could get something like this to work? I'll show some code below. First 7 lines of this code I believe is the only this that is important here but included the whole block just in case.

  <ListView.ItemTemplate>
          <DataTemplate>
            <local:DabViewCell>
              <ViewCell.ContextActions x:Name="ContextAction">
                <MenuItem Clicked="OnListened" IsDestructive="true" Text="Completed" CommandParameter="{Binding .}"/>
                <MenuItem Clicked="OnFavorite" Text="Favorite" CommandParameter="{Binding .}"/>
              </ViewCell.ContextActions>
              <Grid Padding="10,10,10,10" RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=1}" RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,Property=Height,Factor=1}">
                <Grid.RowDefinitions>
                  <RowDefinition Height="Auto"/>
                  <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition Width="*"/>
                  <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <BoxView Color="Transparent" IsVisible="{Binding listenedToVisible, Converter={StaticResource inverser}}" Grid.RowSpan="2" Grid.Column="0" WidthRequest="20" HeightRequest="20" VerticalOptions="Center"/>
                <Image Source="ic_done_listened_3x.png" IsVisible="{Binding listenedToVisible}" Grid.RowSpan="2" Grid.Column="0" WidthRequest="20" HeightRequest="20" VerticalOptions="Center"/>
                <StackLayout Orientation="Horizontal" Grid.Row="0" Grid.Column="1">
                  <local:DabLabel Text="{Binding title}" FontSize="Medium" HorizontalOptions="Start" Style="{StaticResource playerLabelStyle}" FontAttributes="Bold" IsTitle="true" LineBreakMode="TailTruncation"/>
                  <Image IsVisible="{Binding favoriteVisible}" Opacity=".5" HeightRequest="15" Aspect="AspectFit" Source="ic_star_white.png"/>
                  <Image IsVisible="{Binding hasJournalVisible}" Opacity=".5" HeightRequest="15" Aspect="AspectFit" Source="pencil_white.png"/>
                </StackLayout>
                <local:CircularProgressControl Progress="{Binding downloadProgress}" ProgressVisible="{Binding progressVisible}" DownloadVisible="{Binding downloadVisible}" HeightRequest="15" Grid.Column="2" Grid.RowSpan="2"/>
                <local:DabLabel Text="{Binding description}" FontSize="Micro" Grid.Row="1" Grid.Column="1" Style="{StaticResource secondaryLabelStyle}" LineBreakMode="TailTruncation"/>
              </Grid>
            </local:DabViewCell>
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>                     

//UPDATE:

I've noticed that if I comment out the line with await PlayerFeedAPI.UpdateEpisodeProperty() in either of those OnFavorited or OnListened methods then everything responds properly but obviously I still need UpdateEpisodeProperty to run. I've tried making that method not async thinking that could be confusing it but no luck yet. It's not hitting any of my exceptions.. UpdateEpisodeProperty seems to be running fine. Anything pop out to anybody as to why this method is keeping my contextactions from closing on click?

public async void OnFavorite(object o, EventArgs e)
        {
            var mi = ((Xamarin.Forms.MenuItem)o);
            var model = ((EpisodeViewModel)mi.CommandParameter);
            var ep = model.Episode;
            await PlayerFeedAPI.UpdateEpisodeProperty((int)ep.id, null, !ep.is_favorite, null, null);
            await AuthenticationAPI.CreateNewActionLog((int)ep.id, "favorite", null, null, !ep.is_favorite);
            model.favoriteVisible = !ep.is_favorite;
        }
public static async Task UpdateEpisodeProperty(int episodeId, bool? isListened, bool? isFavorite, bool? hasJournal, int? playerPosition, bool RaiseEpisodeDataChanged = true)
        {
            try
            {
                //find the episode
                var episode = db.Table<dbEpisodes>().SingleOrDefault(x => x.id == episodeId);
                if (episode != null) //only update episodes we have in the database
                {
                    //listened
                    if (isListened != null)
                    {
                        episode.is_listened_to = (bool)isListened;
                    }
                    //favorite
                    if (isFavorite.HasValue)
                    {
                        episode.is_favorite = (bool)isFavorite;
                    }
                    //has journal
                    if (hasJournal.HasValue)
                    {
                        episode.has_journal = (bool)hasJournal;
                    }
                    //player position
                    if (playerPosition.HasValue)
                    {
                        if (GlobalResources.CurrentEpisodeId == episode.id)
                        {
                            if (!GlobalResources.playerPodcast.IsPlaying)
                            {
                                //update the active player (only if it is paused)
                                episode.stop_time = playerPosition.Value;
                                episode.remaining_time = (episode.Duration - episode.stop_time).ToString();
                                GlobalResources.playerPodcast.Seek(episode.stop_time);
                            } else
                            {
                                Debug.WriteLine("Skipping seek to new position since episode is playing...");
                            }
                        }
                        //
                    }
                    //save data to the database
                    db.Update(episode);
                }
                else
                {
                    //Store the record in the user-episode meta table for later use
                    dbUserEpisodeMeta meta = db.Table<dbUserEpisodeMeta>().SingleOrDefault(x => x.EpisodeId == episodeId);
                    if (meta == null)
                    {
                        meta = new dbUserEpisodeMeta();
                        meta.EpisodeId = episodeId; 
                    }
                    meta.CurrentPosition = playerPosition;
                    meta.HasJournal = hasJournal;
                    meta.IsFavorite = isFavorite;
                    meta.IsListenedTo = isListened;

                    db.InsertOrReplace(meta);
                    Debug.WriteLine($"Added episode {episodeId} to meta table for later use...");
                }

                //Notify listening pages that episode data has changed 
                if (RaiseEpisodeDataChanged)
                {
                    MessagingCenter.Send<string>("dabapp", "EpisodeDataChanged");
                }
            }
            catch (Exception e)
            {
                //Getting Locked exception on android 
                Debug.WriteLine($"Exception in PlayerFeedAPI.UpdateEpisodeProperty(): {e.Message}");
                DabData.ResetDatabases();
                db = DabData.database;
                adb = DabData.AsyncDatabase;
            }
        }

MessagingCenter within my UpdateEpisodeProperty() got me off the main thread and kept the contextactions menu from closing onClick. What I did to fix this was added a nullable property to my UpdateEpisodeProperty() and if set to false then it would skip the MessagingCenter.Send() for the moment. There were some minor tweeks in my code but basically if I stayed on the main thread then contextactions responded appropriately.

Still think it's odd that before it was working on android and not ios.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM