MvvmCross - How to Add Custom Modal Transition - c#

I am working on a project using MvvmCross and Xamarin. I am trying to add a custom transition when presenting and dismissing my modal view. Currently I am presenting it this way:
[MvxModalPresentation(WrapInNavigationController = true, ModalPresentationStyle = UIModalPresentationStyle.Custom)]
public partial class MyView : MvxViewController
{
and dismissing it this way:
NavigationController.DismissModalViewController(true);
So I have my animation ready, but I am assuming that I need to set the transition delegate to the one I've created. How do I do this?
I am fairly new to MvvmCross, so any tips and tricks are very much appreciated. Thanks!

I Am not sure, what you actually want to achieve here.
If you are looking for syntax help. This should be something like this.
this.NavigationController.TransitioningDelegate = new MyOwnDelegate();
internal class MyOwnDelegate : IUIViewControllerTransitioningDelegate
{
public IntPtr Handle => throw new NotImplementedException();
public void Dispose()
{
//throw new NotImplementedException();
}
}
But normally people use, this one. I am also giving some syntax if that helps
this.NavigationController.Delegate = new NavigationControllerDelegate();
public class NavigationControllerDelegate : UINavigationControllerDelegate
{
public NavigationControllerDelegate(IntPtr handle) : base(handle)
{
}
public NavigationControllerDelegate()
{
}
public override IUIViewControllerAnimatedTransitioning GetAnimationControllerForOperation(UINavigationController navigationController, UINavigationControllerOperation operation, UIViewController fromViewController, UIViewController toViewController)
{
var fromVcConformA = fromViewController as ICustomTransition;
var fromVCConFromB = fromViewController as IWaterFallViewControllerProtocol;
var fromVCCConformc = fromViewController as IHorizontalPageViewControllerProtocol;
var toVcConformA = toViewController as ICustomTransition;
var toVCConfromB = toViewController as IWaterFallViewControllerProtocol;
var toVCCConformc = toViewController as IHorizontalPageViewControllerProtocol;
if ((fromVcConformA != null) && (toVcConformA != null) && ((fromVCConFromB != null && toVCCConformc != null) || (fromVCCConformc != null && toVCConfromB != null)))
{
var transition = new CustomTransition();
transition.presenting = operation == UINavigationControllerOperation.Pop;
return transition;
}
else
{
return null;
}
}
}

Related

how to disable userinteraction of nsview

I am trying to do something similar as UserInteractionEnabled = false in iOS, but it seems that this property is not available in NSView. I also see that one approach is to implement the hittest method to return null, but the hittest for this lass already has a non-trivial implementation and I don't think I can set it to return null. I found a (deprecated) property called acceptsTouchEnabled, and I m wondering if it can achieve the same thing as UserInteractionEnabled.
The project is done in Xamarin, btw.
FreeHandView = new PaintBoardControl
{
BackgroundColor = UIColor.Clear,
TranslatesAutoresizingMaskIntoConstraints = false,
UserInteractionEnabled = false
};
this is the original declaration of the variable, where the UserInteractionEnabled is set to false.
and this is the implementation of the hittest method in my Mac app:
public override NSView HitTest(CGPoint aPoint)
{
aPoint = ContentContainer.ConvertPointFromView(aPoint, this);
aPoint = new CGPoint(aPoint.X + _freehandViewLeftConstraint.Constant,
aPoint.Y + _freehandViewTopConstraint.Constant);
if (_hitTestBitArray != null && aPoint.X >= 0 && aPoint.Y >= 0 &&
_hitTestBitArrayWidth > aPoint.X && _hitTestBitArrayHeight > aPoint.Y)
{
var index = aPoint.Y * _hitTestBitArrayWidth + aPoint.X;
return _hitTestBitArray.Get((int)index) ? this : null;
}
return null;
}
Sometimes hitTest don't work at all try using something like this maybe mousedown can help you
public class ExtendedNSView : NSView
{
public bool IsEnabled { get; set; }
public override void MouseDown(NSEvent theEvent)
{
if (IsEnabled)
{
base.MouseDown(theEvent);
}
}
}

Why C# downcast become always null?

So here is my code,
public void CheckStatChal()
{
foreach (SpotUIBase menu in thisSpot.ownMenus)
{
if (menu.uiSort == SpotUISort.StatEvent)
{
if(menu != null)
Debug.Log("Menu name is "+menu.Name);
var statEvent = menu as StatEvent;
if (statEvent == null)
{
Debug.Log("Stat event is null, name is "+thisSpot.Name);
continue;
}
.......... [1]
public SpecialSpotClass thisSpot;
public abstract class SpecialSpotClass
{
public List<SpotUIBase> ownMenus = new List<SpotUIBase>();
....
public class SpotUIBase
{
public SpotUISort uiSort;
....
public class StatEvent : SpotUIBase
{
....
public enum SpotUISort{
Inn, Shop, Bar,
I am using Unity engine now.
So if run this code, I got
Debug.Log("Menu name is "+menu.Name); and
Debug.Log("Stat event is null, name is "+thisSpot.Name); both.
Why?
menu is not null, but after downcast it, it become null?
I don't understand this why.
So in this code, I want to execute [1] part below codes, but [statEvent] is null,
so all the code below does not called by (continue keyword)
Why downcast become null?
Help please.
So I googled and confirmed right Downcast method, and changed foreach to for syntax.
And solved.
Here is changed code.
for (int i = 0; i < thisSpot.ownMenus.Count; i++)
{
if (thisSpot.ownMenus[i].uiSort == SpotUISort.StatEvent)
{
thisSpot.ownMenus[i] = SpotUI.Instance.StatEvent;
var ownMenu = (StatEvent) thisSpot.ownMenus[i];
Debug.Log("own menu is "+ownMenu.Name);
if ((!ownMenu.StatChal1.nowCoolTime && ownMenu.StatChal1 != null)
|| ownMenu.StatChal1 == null)
{
StatChallenge.Instance.MakeStatChal(this, ref ownMenu.StatChal1);
Debug.Log(ownMenu.StatChal1.Name);
ownMenu.SetChalInfo(ownMenu.StatChal1, 1);
chal1 = ownMenu.StatChal1;
}

Close TabItem from Popup

Here I have a functional CloseTabAction using Prism 6 Toolkit found below:
class CloseTabAction : TriggerAction<Button>
{
protected override void Invoke(object parameter)
{
var args = parameter as RoutedEventArgs;
if (args == null) return;
var tabItem = FindParent<TabItem>(args.OriginalSource as DependencyObject);
if (tabItem == null) return;
var tabControl = FindParent<TabControl>(tabItem);
if (tabControl == null) return;
var region = RegionManager.GetObservableRegion(tabControl).Value;
if (region == null) return;
if (region.Views.Contains(tabItem.Content))
{
region.Remove(tabItem.Content);
}
}
static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
while (true)
{
var parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
var parent = parentObject as T;
if (parent != null) return parent;
child = parentObject;
}
}
}
My problem is I want to close the TabItem only if the user selects 'Yes' (Saves to database and closes) or 'No' (Does not save but closes the tab).
I've created a custom popup window to do this however I'm not sure how to wire it up to the CloseTabAction. How would it know if the conformation is true or false?
This is a rough idea:
if (region.Views.Contains(tabItem.Content) && Status)
{
region.Remove(tabItem.Content);
}
public bool Status { get; set; }
private void RaiseClosePopup()
{
ClosePopupRequest.Raise(new Confirmation{Title = "Confrim", Content = "Are you sure you want to close this view?"}, r => Status = r.Confirmed);
}
I see you watched my Pluralsight course on mastering the TabControl with Prism :)
Why don't you just show a dialog before you call "Remove". If the result of the dialog is valid, then continue to remove, if not then don't remove. Then you just need to decide how you will notify your ViewModel of the action. This can be done a number of ways; event aggregator, expose a property on your CloseTabAction trigger, expose a command on your trigger. You can decide how you want to do that.
EDIT: I actually though of a better way. Just use an interface off of your ViewModel that you check to see if you can close a TabItem. Maybe use the IConfirmNavigationRequest interface or create your own. Then check that before removing he region. That's even easier.
In the invoke method I added this block of code. It checks if it implements my custom 'IConfrimCloseRequest' Interface, then calls the 'ConfrimCloseRequest' Method based from that result close or cancel. If it doesn't implement the interface just close it anyway.
var context = new NavigationContext(region.NavigationService, null);
if (IfImplements<IConfirmCloseRequest>(tabItem.Content,
i => i.ConfirmCloseRequest(context, canClose =>
{
if (!canClose) return;
if (region.Views.Contains(tabItem.Content))
region.Remove(tabItem.Content);
}))) return;
if (region.Views.Contains(tabItem.Content))
region.Remove(tabItem.Content);
private static T Implementor<T>(object content) where T : class
{
T implementor = content as T;
if (implementor != null) return implementor;
var element = content as FrameworkElement;
if (element != null) implementor = element.DataContext as T;
return implementor;
}
private static bool IfImplements<T>(object content, Action<T> action) where T : class
{
T target = Implementor<T>(content);
if (target == null) return false;
action(target);
return true;
}
Here In my ViewModel I implement my custom Interface with the method 'ConfirmCloseRequest' which will be called when closing the tab.
public void ConfirmCloseRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
ClosePopupRequest.Raise(new Confirmation { Title = "Confrim", Content = "Are you sure you want to close this view?" }, r => { continuationCallback(r.Confirmed); });
}

Create a generic type to find implementations of in a Resharper plugin

I'm writing a plugin for resharper which I want to use to navigate from a ConcreteCommand -> ConcreteCommandHandler where those types look like this
public class ConcreteCommand : ICommand
public class ConcreteCommandHandler : ICommandHandler<ConcreteCommand>
I've got as far as adding my navigation menu option when the cursor is on a ICommand instance/definition (currently only by checking if the name contains 'Command' and not 'CommandHandler'), and I think I have the code necessary to actually search for a type which inherits something, but my issue is that the only thing I actually have a type for is my ConcereteCommand and I need to create (or get a reference to) the generic type ICommandHandler<T> with T being the type the cursor is currently on.
So I have 2 things I still want to know:
How can I check if my IDeclaredElement is an implementation of a particular interface (ideally by specifying the full name in a string from config)?
How can I create a ITypeElement which is a generic type of a specific interface where I can set the generic type from my existing IDeclaredElements type, so I can then find classes which inherit this?
My existing code looks like this:
[ContextNavigationProvider]
public class CommandHandlerNavigationProvider : INavigateFromHereProvider
{
public IEnumerable<ContextNavigation> CreateWorkflow(IDataContext dataContext)
{
ICollection<IDeclaredElement> declaredElements = dataContext.GetData(DataConstants.DECLARED_ELEMENTS);
if (declaredElements != null || declaredElements.Any())
{
IDeclaredElement declaredElement = declaredElements.First();
if (IsCommand(declaredElement))
{
var solution = dataContext.GetData(JetBrains.ProjectModel.DataContext.DataConstants.SOLUTION);
yield return new ContextNavigation("This Command's &handler", null, NavigationActionGroup.Other, () => { GotToInheritor(solution,declaredElement); });
}
}
}
private void GotToInheritor(ISolution solution, IDeclaredElement declaredElement)
{
var inheritorsConsumer = new InheritorsConsumer();
SearchDomainFactory searchDomainFactory = solution.GetComponent<SearchDomainFactory>();
//How can I create the ITypeElement MyNameSpace.ICommandHandler<(ITypeElement)declaredElement> here?
solution.GetPsiServices().Finder.FindInheritors((ITypeElement)declaredElement, searchDomainFactory.CreateSearchDomain(solution, true), inheritorsConsumer, NullProgressIndicator.Instance);
}
private bool IsCommand(IDeclaredElement declaredElement)
{
//How can I check if my declaredElement is an implementation of ICommand here?
string className = declaredElement.ShortName;
return className.Contains("Command")
&& !className.Contains("CommandHandler");
}
}
Ok managed to work this out with a fair bit of pushing in the right direction from #CitizenMatt.
basically my solution looks like this (still needs some tidying up)
private static readonly List<HandlerMapping> HandlerMappings = new List<HandlerMapping>
{
new HandlerMapping("HandlerNavigationTest.ICommand", "HandlerNavigationTest.ICommandHandler`1", "HandlerNavigationTest"),
new HandlerMapping("HandlerNavTest2.IEvent", "HandlerNavTest2.IEventHandler`1", "HandlerNavTest2")
};
public IEnumerable<ContextNavigation> CreateWorkflow(IDataContext dataContext)
{
ICollection<IDeclaredElement> declaredElements = dataContext.GetData(DataConstants.DECLARED_ELEMENTS);
if (declaredElements != null && declaredElements.Any())
{
IDeclaredElement declaredElement = declaredElements.First();
ISolution solution = dataContext.GetData(JetBrains.ProjectModel.DataContext.DataConstants.SOLUTION);
ITypeElement handlerType = GetHandlerType(declaredElement);
if (handlerType != null)
{
yield return new ContextNavigation("&Handler", null, NavigationActionGroup.Other, () => GoToInheritor(solution, declaredElement as IClass, dataContext, handlerType));
}
}
}
private static ITypeElement GetHandlerType(IDeclaredElement declaredElement)
{
var theClass = declaredElement as IClass;
if (theClass != null)
{
foreach (IPsiModule psiModule in declaredElement.GetPsiServices().Modules.GetModules())
{
foreach (var handlerMapping in HandlerMappings)
{
IDeclaredType commandInterfaceType = TypeFactory.CreateTypeByCLRName(handlerMapping.HandledType, psiModule, theClass.ResolveContext);
ITypeElement typeElement = commandInterfaceType.GetTypeElement();
if (typeElement != null)
{
if (theClass.IsDescendantOf(typeElement))
{
IDeclaredType genericType = TypeFactory.CreateTypeByCLRName(handlerMapping.HandlerType, psiModule, theClass.ResolveContext);
ITypeElement genericTypeElement = genericType.GetTypeElement();
return genericTypeElement;
}
}
}
}
}
return null;
}
private static void GoToInheritor(ISolution solution, IClass theClass, IDataContext dataContext, ITypeElement genericHandlerType)
{
var inheritorsConsumer = new InheritorsConsumer();
var searchDomainFactory = solution.GetComponent<SearchDomainFactory>();
IDeclaredType theType = TypeFactory.CreateType(theClass);
IDeclaredType commandHandlerType = TypeFactory.CreateType(genericHandlerType, theType);
ITypeElement handlerTypeelement = commandHandlerType.GetTypeElement();
solution.GetPsiServices().Finder.FindInheritors(handlerTypeelement, searchDomainFactory.CreateSearchDomain(solution, true),
inheritorsConsumer, NullProgressIndicator.Instance);
var potentialNavigationPoints = new List<INavigationPoint>();
foreach (ITypeElement inheritedInstance in inheritorsConsumer.FoundElements)
{
IDeclaredType[] baseClasses = inheritedInstance.GetAllSuperTypes();
foreach (IDeclaredType declaredType in baseClasses)
{
if (declaredType.IsInterfaceType())
{
if (declaredType.Equals(commandHandlerType))
{
var navigationPoint = new DeclaredElementNavigationPoint(inheritedInstance);
potentialNavigationPoints.Add(navigationPoint);
}
}
}
}
if (potentialNavigationPoints.Any())
{
NavigationOptions options = NavigationOptions.FromDataContext(dataContext, "Which handler do you want to navigate to?");
NavigationManager.GetInstance(solution).Navigate(potentialNavigationPoints, options);
}
}
public class InheritorsConsumer : IFindResultConsumer<ITypeElement>
{
private const int MaxInheritors = 50;
private readonly HashSet<ITypeElement> elements = new HashSet<ITypeElement>();
public IEnumerable<ITypeElement> FoundElements
{
get { return elements; }
}
public ITypeElement Build(FindResult result)
{
var inheritedElement = result as FindResultInheritedElement;
if (inheritedElement != null)
return (ITypeElement) inheritedElement.DeclaredElement;
return null;
}
public FindExecution Merge(ITypeElement data)
{
elements.Add(data);
return elements.Count < MaxInheritors ? FindExecution.Continue : FindExecution.Stop;
}
}
And this allows me no navigate to multiple handlers if they exist. This currently relies on the interfaces for the handled type and the handler type being in the same assembly. But this seems reasonable enough for me at the moment.

Implement System.Web.Caching.Cache Object in a controller to cache specific query

Is it correct to implement my caching object like this in my controller :
public class HomeController : BaseController
{
public static Cache cachingControl = new Cache();
...
And I Use it like this :
public ActionResult Home()
{
IndexViewData view = new IndexViewData();
view.UserId = UserId;
if (cachingControl.Get("viewHome") != null) {
view = (IndexViewData)cachingControl.Get("viewHome");
} else {
view.allAdsList = AllAds(5000, 0);
if (Request.QueryString["voirTous"] != null)
view.loadGeneral(true);
else
view.loadGeneral(false);
cachingControl.Insert("viewHome", view);
}
view.adsList = SetupSearch(5, false, 0);
return View(view);
}
But When I Call this line :
if (cachingControl.Get("viewHome") != null) {
They trow me the error
NullErrorException
But I know it can be null this is why i'm put this condition to
Do you have an alternative or a tips for me thank you!
P.S.: I Know that the code is weird :P but I must to support it ...
The System.Web.Caching.Cache object is available already for you by adding this to the controller:
this.HttpContext.Cache
That is the already in-built cache that's also available in web forms.

Categories