/// <summary>
 /// Returns true if parameter has a value that can lead to a holder.
 /// </summary>
 /// <param name="parameter">
 /// Could be a container id ( <c>string</c>), container ( <see cref="ItemsControl"
 /// />), or holder ( <see cref="ContentControl" />).
 /// </param>
 /// <returns></returns>
 public bool CanExecute(object parameter)
 {
     try
     {
         var holder = MvxCloseViewCommand.GetHolder(parameter);
         if (holder == null)
         {
             return(true);
         }
         return(!MvxContainer.GetHasClosingAction(holder));
     }
     catch (Exception)
     {
     }
     return(true);
 }
        /// <summary>
        /// Execute a close command on a holder.
        /// </summary>
        /// <param name="parameter">
        /// Could be a container id ( <c>string</c>), container ( <see cref="ItemsControl"
        /// />), or holder ( <see cref="ContentControl" />).
        /// </param>
        /// <remarks>
        /// If the parameter is <see cref="string" />, the command will search for the
        /// container of same id and if the parameter is <see cref="ItemsControl" /> it
        /// will use it as a container. In both cases the command will get the selected
        /// holder in the container (if it is a <see cref="Selector" />) or it will use
        /// the last holder in the items collection. The close command is will close all
        /// the views in the holder navigation stack.
        /// </remarks>
        public async void Execute(object parameter)
        {
            var holder = MvxCloseViewCommand.GetHolder(parameter);

            if (holder == null)
            {
                throw new InvalidCastException("Command parameter should be a content control.");
            }
            var history = MvxContainer.GetHolderHistory(holder);

            if (history != null)
            {
                MvxContainer.SetHasClosingAction(holder, true);
                RaiseCanExecuteChanged();
                var nav = Mvx.IoCProvider.Resolve <IMvxNavigationService>();
                foreach (var mv in history.Select((c) => MvxWpfPresenter.GetViewModel(c)).ToList())
                {
                    await nav.Close(mv);
                }
                MvxContainer.SetHasClosingAction(holder, false);
                RaiseCanExecuteChanged();
            }
        }
        internal static ContentControl GetHolder(object parameter)
        {
            var            container = parameter as ItemsControl;
            ContentControl holder    = null;

            if (container == null && parameter is string id)
            {
                container = MvxContainer.GetContainerById(id);
            }
            if (container != null && container.Items.Count > 0)
            {
                if (container is Selector selector)
                {
                    holder = selector.SelectedItem as ContentControl;
                }
                holder = container.Items[container.Items.Count - 1] as ContentControl;
            }
            if (holder == null)
            {
                holder = parameter as ContentControl;
            }
            return(holder);
        }
        /// <summary>
        /// Execute a back command on a holder.
        /// </summary>
        /// <param name="parameter">
        /// Could be a container id ( <c>string</c>), container ( <see cref="ItemsControl"
        /// />), or holder ( <see cref="ContentControl" />).
        /// </param>
        /// <remarks>
        /// If the parameter is <see cref="string" />, the command will search for the
        /// container of same id and if the parameter is <see cref="ItemsControl" /> it
        /// will use it as a container. In both cases the command will get the selected
        /// holder in the container (if it is a <see cref="Selector" />) or it will use
        /// the last holder in the items collection. The back command is actually a close
        /// command for the last view in the holder.
        /// </remarks>
        public void Execute(object parameter)
        {
            var holder = GetHolder(parameter);

            if (holder == null)
            {
                return;
            }
            var view = holder.Content as FrameworkElement;

            if (view == null)
            {
                return;
            }
            object vm = null;

            if (view is MvvmCross.Views.IMvxView mvxv)
            {
                vm = mvxv.ViewModel;
            }
            if (vm == null)
            {
                vm = view.DataContext;
            }
            if (vm == null)
            {
                return;
            }
            MvxContainer.SetHasClosingAction(holder, true);
            RaiseCanExecuteChanged();
            var nav = Mvx.IoCProvider.Resolve <MvvmCross.Navigation.IMvxNavigationService>();

            nav.Close(vm as MvvmCross.ViewModels.IMvxViewModel);
            MvxContainer.SetHasClosingAction(holder, false);
            RaiseCanExecuteChanged();
        }