Xamarin forms: Adjacent tab get called when open a tab - xamarin.forms

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].

Related

How to display content View over the tabs of tabbed page

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:

ASP.NET| checkbox's "checked=true" is not setted in the right checkbox

I'm working on a simple multi-staged registration page for a site I'm building, and I give the user the choice of choosing programs/programming languages he knows using checkboxes:
but when I hit the "next" button, in order to go to the next stage, the checkbox I checked isn't set to true, but checkbox no. 18 is set to true(although I didn't check it)
I'm certain it has something to do with the stage before this one, in which I'm building dynamically radio buttons in which the user is choosing his profession (such as Artist, singer and etc').
there are 17 radio buttons, and they are somehow interfering with the next stage, in which the checkbox's checked values are only starting from checkbox no. 18 as I mentioned earlier.
here is some of the code:
else if (int.Parse(ViewState["DivID"].ToString()) == 2)
{
// save the Birthday Date, Language and country of the user.
ViewState["year"] = int.Parse(DropDownYear.SelectedValue);
ViewState["month"] = int.Parse(DropDownMonth.SelectedValue);
ViewState["day"] = int.Parse(DropDownDay.SelectedValue);
ViewState["Language"] = int.Parse(langDropDown.SelectedValue);
ViewState["Country"] = int.Parse(CountryDropDown.SelectedValue);
// ---------------------------------------------
// change from part 2 of the registration to part 3
registrationP2.Visible = false;
BindProfessions(radios, Page);
registrationP3.Visible = true;
radios.Visible = true;
}
else if (int.Parse(ViewState["DivID"].ToString()) == 3)
{
// change from part 3 of the registration to part 4
ViewState["Profid"] = CheckRadio(radios);
registrationP3.Visible = false;
BindKnowledge(CheckboxCon, Page);
registrationP4.Visible = true;
CheckboxCon.Visible = true;
// ---------------------------------------------
//next.Visible = true;
}
else if(int.Parse(ViewState["DivID"].ToString()) == 4)
{
List<int> v = GetCheckBox(CheckboxCon);
ViewState["Knowids"] = GetCheckBox(CheckboxCon);
}
Binding methods:
public static void BindProfessions(HtmlControl ctrl, Page thispage)
{
List<Profession> Plist = Profession.GetProfessionList();
foreach (Profession p in Plist)
{
HtmlInputRadioButton rd_button = new HtmlInputRadioButton();
const string GROUP_NAME = "Professions";
rd_button.Name = GROUP_NAME;
string LinkID = "P" + p.ProfessionID.ToString();
rd_button.Attributes["id"] = LinkID;
RegisterUserControl userprofession = (RegisterUserControl)thispage.LoadControl("~/RegisterUserControl.ascx");
userprofession.imgP = p.ProfPath;
userprofession.fieldName = p.ProfName;
userprofession.IDnum = p.ProfessionID;
userprofession.RadioName = LinkID;
userprofession.EnableViewState = false;
rd_button.EnableViewState = false;
ctrl.Controls.Add(rd_button);
rd_button.Value = p.ProfessionID.ToString();
ctrl.Controls.Add(userprofession);
}
}
public static void BindKnowledge(HtmlControl ctrl, Page thispage)
{
List<Knowledge> Plist = Knowledge.RetKnowledgeList();
foreach (Knowledge p in Plist)
{
HtmlInputCheckBox rd_button = new HtmlInputCheckBox();
const string GROUP_NAME = "knowledge";
rd_button.Name = GROUP_NAME;
string LinkID = "Know" + p.ProgramID.ToString();
rd_button.Attributes["id"] = LinkID;
rd_button.Value = p.ProgramID.ToString();
RegisterUserControl userprofession = (RegisterUserControl)thispage.LoadControl("~/RegisterUserControl.ascx");
userprofession.imgP = p.ProgPath;
userprofession.fieldName = p.PName;
userprofession.IDnum = p.ProgramID;
userprofession.RadioName = LinkID;
userprofession.EnableViewState = false;
rd_button.EnableViewState = false;
ctrl.Controls.Add(rd_button);
ctrl.Controls.Add(userprofession);
}
}
checking methods for both radios and checkbox :
public static int CheckRadio(HtmlControl ctrl)
{
try
{
int counter = 0;
int id = -1;
foreach (Control rdButton in ctrl.Controls)
{
if (rdButton is HtmlInputRadioButton)
{
HtmlInputRadioButton bu = (HtmlInputRadioButton)rdButton;
if (bu.Checked)
{
counter++;
id = int.Parse(bu.Value);
}
}
}
if (counter > 1)
{
return -1;
}
return id;
}
catch (Exception e)
{
return -1;
}
}
public static List<int> GetCheckBox(HtmlControl ctrl)
{
List<int> id_list = new List<int>();
foreach (Control rdButton in ctrl.Controls)
{
if (rdButton is HtmlInputCheckBox)
{
HtmlInputCheckBox bu = (HtmlInputCheckBox)rdButton;
if (bu.Checked)
{
id_list.Add(int.Parse(bu.Value));
}
}
}
return id_list;
}
}
when debugging you can see, that if I choose the first 3 professions, the values returned to me in the List<int> v are 18, 19, and 20
photo: debugging photo
I should mention that after I create the dynamic usercontrols and checkbox/radion buttons, I'm creating them again at postback in protected void Page_Load.
I'm stuck on this for days, and I don't know from where the problem emanates, is it because of ViewState, or the way I'm creating the controls... I really don't know.
Thanks in advance, Idan.
edit:
I played with it a bit, and have found out that when I disable the Binding of the professions which I have initiated earlier in Page_load it does work correctly, page load code look at the second if statement :
protected void Page_Load(object sender, EventArgs e)
{
IsPageRefresh = false;
if (!IsPostBack)
{
ViewState["DivID"] = 1;
ViewState["postids"] = System.Guid.NewGuid().ToString();
Session["postid"] = ViewState["postids"].ToString();
}
else
{
if (ViewState["postids"].ToString() != Session["postid"].ToString())
{
IsPageRefresh = true;
}
Session["postid"] = System.Guid.NewGuid().ToString();
ViewState["postids"] = Session["postid"].ToString();
}
if (int.Parse(ViewState["DivID"].ToString()) == 3)
{
//BindProfessions(radios, Page);
}
else if(int.Parse(ViewState["DivID"].ToString()) == 4)
{
BindKnowledge(CheckboxCon, Page);
}
}
the problem is that I still need to initiate it again after hitting the button in order to get the checked value, how can I fix this thing, and why this is happening? your help would very much be appreciated.
The problem happens because the page recognize that I added 17 new checkbox's, and than when I go over them the first 17 are not checked until the 18'th(the first one of the ones that I checked) what ends up not checking the right checkbox....
And to make it clears I add the other radio buttons to a different div on the page, I don't know what is happening here
for anyone who has the same problem.
I ended up creating the object in Page_PreInit() and it solved the problem, it is recommended(by things I read) to create dynamic objects in Page_PreInit, before anything else is happening to the page.
protected void Page_PreInit(object sender, EventArgs e)
{
try
{
if (!IsPostBack && Session["DivID"] == null)
{
Session["DivID"] = 1;
}
if ((int)Session["DivID"] == 3)
{
InitBindProfessions(Page);
}
else if ((int)Session["DivID"] == 4)
{
InitBindKnowledge(Page);
}
}
catch
{
Response.Redirect("HomePage.aspx");
}
}
InitBindKnowledge and InitBindProfessions are just like BindKnowledge and BindProfession but without adding usercontrols to the control tree

Xamarin forms: Auto scrolling for CarouselPage children

I have 4 children (page1,page2,page3, and page4) in a CarouselPage, I need to auto-scroll the children in every 3 seconds. Initially, page1 is showing on the UI, then page2 -> page3 -> page 4 again starting from page1.
I have done like below for this feature using OnCurrentPageChanged() and await Task.Delay(TimeSpan.FromSeconds(3));:
protected async override void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();
await Task.Delay(TimeSpan.FromSeconds(3));
int index = Children.IndexOf(CurrentPage);
if (index == 0)
{
CurrentPage = Children[1];
}
else if (index == 1)
{
CurrentPage = Children[2];
}
else if (index == 2)
{
CurrentPage = Children[3];
}
else if (index == 3)
{
CurrentPage = Children[0];
}
}
The auto-scroll is successful by this approach.
But if I manually scroll the page in between the auto-scroll, then the time delay is reducing. Suddenly(less than 3 sec) the next page is showing on the screen. If I manually swipe the page I need to wait on the page for 3 seconds. How can I solve this issue?
There is a Exciting Library CardsView please look into it.
it will not only solve your problem but your apps looks cool as well.
here is Source Project , https://github.com/AndreiMisiukevich/CardView .
check CarouselSampleXamlView in that, SlideShowDuration property for carousel which handles all stuff.
Hope it helps.
Please do not put the transfer page to the OnCurrentPageChanged method.
You can put it in your Page's constructor.
public partial class MainPage : CarouselPage
{
bool isStart = true;
public MainPage()
{
InitializeComponent();
Device.StartTimer(new TimeSpan(0, 0, 3), () =>
{
Device.BeginInvokeOnMainThread(() =>
{
int index = Children.IndexOf(CurrentPage);
if (index == 0)
{
CurrentPage = Children[1];
isStart = true;
}
else if (index == 1)
{
CurrentPage = Children[2];
isStart = true;
}
else if (index == 2)
{
CurrentPage = Children[3];
isStart = true;
}
else if (index == 3)
{
CurrentPage = Children[0];
isStart = true;
}
});
return isStart; // runs again, or false to stop
});
}
}
If you change the page by swipe, the time delay is not reducing.
However, If you want to wait on the page for 3 seconds after swiping. You have to use custom renderer to achieve it. You should monitor the viewpager's onTouchEventin android(but I cannot found a solution in IOS). This way will have caton, so above way will be better.
[assembly: ExportRenderer(typeof(CarouselPage), typeof(CustomCarouselPageRenderer))]
namespace CarouselPageDemo.Droid
{
public class CustomCarouselPageRenderer: CarouselPageRenderer
{
public CustomCarouselPageRenderer(Context context) : base(context) {
}
protected override void OnElementChanged(ElementChangedEventArgs<CarouselPage> e)
{
base.OnElementChanged(e);
if (this.ChildCount > 0 && this.GetChildAt(0) is ViewPager viewPager)
{
viewPager.Touch -= ViewPagerTouched;
viewPager.Touch += ViewPagerTouched;
}
}
private void ViewPagerTouched(object sender, TouchEventArgs e)
{
MessagingCenter.Send<App, string>(App.Current as App, "OpenPage", "stop");
}
}
}
CarouselPage_CurrentPageChanged method
private async void CarouselPage_CurrentPageChanged(object sender, EventArgs e)
{
var tokenSource = new CancellationTokenSource();
await Task.Delay(TimeSpan.FromSeconds(3), tokenSource.Token);
MessagingCenter.Subscribe<App, string>(App.Current, "OpenPage", (snd, arg) =>
{
tokenSource.Cancel();
});
int index = Children.IndexOf(CurrentPage);
if (index == 0)
{
CurrentPage = Children[1];
}
else if (index == 1)
{
CurrentPage = Children[2];
}
else if (index == 2)
{
CurrentPage = Children[3];
}
else if (index == 3)
{
CurrentPage = Children[0];
}
}

Not able to maintain checkbox during pagination using jQuery

I have 4 buttons for pagination(first,move next,move back and last).
I am trying to maintain checkbox during pagination. The problem is that
when I select any checkbox and then go to next page and then come back to the same page, it doesn't show previously checked checkbox, but as soon as click on next page, before going to next page it shows value checked.
Here is my code, can anyone guide me where I am doing wrong?
$(function() {
toggleSelectBtnOnCheck();
});
function toggleSelectBtnOnCheck() {
debugger;
//Register checkbox click handler to be called when Ajax requests complete.
$('#contentDiv').ajaxComplete(function() {
$('.tdHeadForCheckboxRadioButton').append('<input class="search" onclick="checkUnchekAllCheckboxes(this);" type="checkbox"/>');
$('.afirst, .aprev, .anext, .alast, .search:checkbox').click(function() {
var selectedVal = $(this).closest('td');
var selectClaim = selectedVal.next().text();
var selectSuffix = selectedVal.next().next().text();
var ClaimSuffix = selectClaim + '|' + selectSuffix + ',';
if ($(this).is(':checked')) {
document.getElementById('hdnChkClaim').value += ClaimSuffix;
} else if ($('#hdnChkClaim').val().indexOf(ClaimSuffix) != -1) {
$('#hdnChkClaim').val($('#hdnChkClaim').val().replace(ClaimSuffix, ''));
}
alert($('#hdnChkClaim').val());
if (jQuery(this).attr("href") != "") {
//button.disable($('span.btnSelect'));
var SelectedItemsCheckboxID = [];
if ($('#hdnChkClaim').val() != '') {
debugger;
if (ClaimSuffix.indexOf(',') != -1) {
ClaimSuffix = ClaimSuffix.substr(0, ClaimSuffix.length - 1); //remove last ','
}
SelectedItemsCheckboxID = $('#hdnChkClaim').val().split(',');
for (i = 0; i < SelectedItemsCheckboxID.length; i++) {
var claimDetails = SelectedItemsCheckboxID[i].split('|');
a = claimDetails[0];
b = claimDetails[1];
$('tr').filter(function(index) {
var columns = $(this).children('td');
alert(columns.eq(1).text() === a && columns.eq(2).text() === b);
return columns.eq(1).text() === a && columns.eq(2).text() === b;
}).find('input:checkbox').attr("checked", true);
;
}
}
if ($('.search:checkbox:checked').length > 0) {
button.enable($('span.btnSelect'));
} else {
button.disable($('span.btnSelect'));
}
}
});
});
}
You have to use the hidden field , when user select a checkbox , add it to hidden field like comma separated Ids , when every page is moved because of pagination check if any of the id in the current page is belong to the hidden field if yes mark them to checked.

Caliburn.micro : Bind two views of ViewModel with tab Control

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.

Resources