I am working on a tabbed page with 4 tabs. In the second tab, I have a display list of names. I have created a content view to display it as a popup and added that in my second tab.
The problem is the popup (content view) is not displaying from the top. It is displaying below the tabs. Even I tried with layout options as start and expand the position is the same.
I have to display it from the top (over the tabs below the Navigation bar), can somebody please help me with this.
Edit:
Popup design
Calling popup: This is the child of the tabbed page
The problem is the popup (content view) is not displaying from the top.
From Rg.plugins.popup document , can custom animations as follow:
https://github.com/rotorgames/Rg.Plugins.Popup/wiki/Animations#custom-animations
Creat UserAnimation class:
class UserAnimation : MoveAnimation
{
private double _defaultTranslationY;
public UserAnimation()
{
DurationIn = DurationOut = 300;
EasingIn = Easing.SinOut;
EasingOut = Easing.SinIn;
PositionIn = MoveAnimationOptions.Top;
PositionOut = MoveAnimationOptions.Top;
}
public override void Preparing(View content, PopupPage page)
{
base.Preparing(content, page);
page.IsVisible = false;
if (content == null) return;
_defaultTranslationY = content.TranslationY;
}
public override void Disposing(View content, PopupPage page)
{
base.Disposing(content, page);
page.IsVisible = true;
if (content == null) return;
content.TranslationY = _defaultTranslationY;
}
public async override Task Appearing(View content, PopupPage page)
{
var taskList = new List<Task>();
taskList.Add(base.Appearing(content, page));
if (content != null)
{
//top
var topOffset = GetTopOffset(content, page);
content.TranslationY = -topOffset;
taskList.Add(content.TranslateTo(content.TranslationX, _defaultTranslationY, DurationIn, EasingIn));
};
page.IsVisible = true;
await Task.WhenAll(taskList);
}
public async override Task Disappearing(View content, PopupPage page)
{
var taskList = new List<Task>();
taskList.Add(base.Disappearing(content, page));
if (content != null)
{
//top
_defaultTranslationY = content.TranslationX;
var topOffset = -GetTopOffset(content, page);
taskList.Add(content.TranslateTo(content.TranslationX, topOffset, DurationOut, EasingOut));
};
await Task.WhenAll(taskList);
}
}
Usage:
<pages:PopupPage.Animation>
<animations:UserAnimation />
</pages:PopupPage.Animation>
Screenshot:
Related
I am using TabbedPage for implementing tabs in my apps. I have 4 tabs and always open the second tab initially since the first tab is the home tab. When selecting the second tab third tab is also loading in the background and when selecting the third tab fourth tab is also loading in the background.
TabbedPage Code:
var homePage = new Pages.HomePage()
{
Title = "Home"
};
var secondPage= new SecondPage()
{
Title = "SecondPage"
};
var thirdPage = new ThirdPage()
{
Title = "ThirdPage"
};
var fourthPage = new FourthPage()
{
Title = "FourthPage"
};
Children.Add(homePage);
Children.Add(secondPage);
Children.Add(thirdPage);
Children.Add(fourthPage);
CurrentPage = Children[1];
this.CurrentPageChanged += (object sender, EventArgs e) =>
{
var i = this.Children.IndexOf(this.CurrentPage);
if (i == 0)
{
CallHomePage();
}
else if (i == 1)
{
//SecondPage icon settings
}
else if (i == 2)
{
//ThirdPage icon settings
}
else if (i == 3)
{
//FourthPage icon settings
}
};
How can I stop the loading of the adjacent tab when selecting a tab?
Solution: You can get the index of currentPage in method OnCurrentPageChanged And if the index equals 1(second page) , use the messagecenter to send message to the page.Refer the following code .
in Tabbed Page
protected override void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();
int index = Children.IndexOf(CurrentPage);
if (index == 1)
{
MessagingCenter.Send<Object>(this, "click_second_tab");
}
else if (index == 2)
{
MessagingCenter.Send<Object>(this, "click_third_tab");
}
else if (index == 3)
{
//...
}
}
in the second page .Move the code that load data from onAppearing to the constructor
public SecondPage()
{
//...
MessagingCenter.Subscribe<Object>(this, "click_second_tab", (obj) =>
{
//load your data here
});
}
Well, as with all arrays/lists in C#, the Children list is zero-indexed, which means the first element is at Children[0].
i have this issue wherein i need to get the navigation bar height in my Dependency Service.
Currently I am stuck on what to follow here. I tried everything i find in stackoverflow and google but no one works for me.
Heres my code:
[assembly: Dependency(typeof(DeviceInfo))]
namespace Wicket.App.Mobile.iOS.Framework
{
public class DeviceInfo : IDeviceInfo
{
public float StatusBarHeight => (float)UIApplication.SharedApplication.StatusBarFrame.Size.Height;
public float NavigationBarHeight => GetNavigationBarHeight();
public static UINavigationController NavigationController { get; set; }
public float GetNavigationBarHeight()
{
//Get navigation bar height
return 0;
}
}
}
I already completed the android part and it works good. The only problem now is in iOS. I have tried getting the instance of navigationcontroller in AppDelegate so that I can just get the bar frame like this NavigationBar.Bounds.Height;
I think this should work:
var navheight = GetTopViewController().NavigationController.NavigationBar.Frame.Height;
public static UIViewController GetTopViewController()
{
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
vc = vc.PresentedViewController;
if (vc is UINavigationController navController)
vc = navController.ViewControllers.Last();
return vc;
}
Solution:
How about pass an instance of viewController as parameter in the function inside the IDeviceInfo?
Try this:
public void getNaviHeight(ContentPage vc)
{
var renderer = Platform.GetRenderer(vc);
if (renderer == null)
{
renderer = RendererFactory.GetRenderer(vc);
Platform.SetRenderer(vc, renderer);
}
var viewController = renderer.ViewController;
var h = viewController.NavigationController?.NavigationBar.Frame.Height;
}
And use the dependency:
public MainPage ()
{
DependencyService.Get<IDeviceInfo>().getNaviHeight(this);
}
this worked to me:
var navigationBar = UIApplication.SharedApplication.KeyWindow.RootViewController.View.Subviews[0].Subviews.OfType<UINavigationBar>().FirstOrDefault();
if(navigationBar != null)
{
// continue here...
}
I have a dynamically generated menu (C#), like this:
MenuItem(string text, string value, string imageUrl, string navigateUrl, string target)
MenuItem AdminLevel1 = new MenuItem("Admin", "Admin"); MenuItem AdminPedidosRegisto = new MenuItem("Questions", "AdminQ");
NavigationMenu.Items.Add(new MenuItem("Messages Received", "AdminMessagesR", "", "./Admin/Messages.ascx", "ContainerIframe")); AdminPedidosRegisto.ChildItems.Add(new MenuItem("Pending", "AdminPending", "", "./Admin/Pedidos.ascx", "ContainerIframe"));
Where 'ContainerIframe' is the iFrame's ID and 'NavigationMenu' is the (asp:Menu)'s ID.
I want to disable the click action in the parent items that don't have an URL set, so the page doesn't refresh when someone clicks it.
Is there a way?
menuitem.NavigateUrl = "javascript:;";
Thanks to #Manibhadra (this is enough for parent items and child items)
window.onload = function ()
{
var menuTable = document.getElementById("<%=NavigationMenu.ClientID%>");
var menuLinks = menuTable.getElementsByTagName("a");
for (i = 0; i < menuLinks.length; i++)
{
menuLinks[i].onclick = function () { }
}
}
if (MenuItem.NavigateUrl == "")
{
MenuItem.Selectable = false;
}
I'm trying to figure out how to add text to the bottom of a list box and display it. In WPF with code behind, I would grab the ScrollViewer and manipulate it, but I can't figure out how to do it with Caliburn...
You have a couple options.
1) In your ViewModel you can call GetView and cast it to your view type and get a reference to the ScrollViewer. Something like:
var myView = this.GetView() as MyView;
var myScrollView = myView.MyScrollView;
That works fine but isn't ideal if you're trying to not couple the view to the view model.
Option 2) is to implement IResult, see docs here.
public class ScrollViewResult : IResult
{
public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
private ScrollViewResult ()
{
}
public void Execute (ActionExecutionContext context)
{
var view = context.View as FrameworkElement;
var scrollViewer = FindVisualChild<ScrollViewer>(view);
//do stuff to scrollViewer here
Completed (this, new ResultCompletionEventArgs { });
}
private static TChildItem FindVisualChild<TChildItem> (DependencyObject obj)
where TChildItem : DependencyObject
{
for (var i = 0; i < VisualTreeHelper.GetChildrenCount (obj); i++)
{
var child = VisualTreeHelper.GetChild (obj, i);
if (child != null && child is TChildItem)
return (TChildItem)child;
var childOfChild = FindVisualChild<TChildItem> (child);
if (childOfChild != null)
return childOfChild;
}
return null;
}
//this isn't required of course but comes in handy for
//having a static method and passing parameters to the
//ctor of the IResult
public static IResult DoSomething ()
{
return new ScrollViewResult ();
}
Then you can call it like:
public IEnumerable<IResult> SomeAction()
{
yield return ScrollViewResult.DoSomething();
}
I am trying to bind two views of viewmodel to two tabs of tab control by editing sample source code Caliburn.Micro.SimpleMDI included with Caliburn.Micro source. This project contains ShellViewModel and TabViewModel with TabView. I added one View named TabViewDetails. I edited ShellViewModel as follows.
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
{
int count = 1;
public void OpenTab()
{
TabViewModel vm = null;
if (Items.Count != 0)
{
vm = new TabViewModel() { DisplayName = "Detail Tab " + count++ };
var secondView = new TabViewDetails();
ViewModelBinder.Bind(vm, secondView , null);
}
else
{
vm = new TabViewModel() { DisplayName = "Tab " + count++ };
}
ActivateItem(vm);
}
}
First tab is Ok. But the second tab shows nothing.Can anybody help to figure out the problem?.
I haven't used Caliburn.Micro much but the simple solution is one view, one view model. If you change your code to something like:
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive {
int count = 1;
public void OpenTab()
{
Screen screen;
if (count != 0)
{
screen = new TabViewModel
{
DisplayName = "Tab " + _count++
};
}
else
{
screen = new TestViewModel
{
DisplayName = "Tab " + _count++
};
}
ActivateItem(screen);
}
}
where TestViewModel can be a TabViewModel
public class TestViewModel : TabViewModel
{
}
then this works ok.
The Caliburn docs does have a section multiple views over the same viewmodel but I haven't figured that out yet.