XAMARIN prevent page loading after tap on ShellContent (DataTemplate) - xaml

I made some progress on my android app. Currently I struggle to find solution to this problem
(Code reference in my older question Creating nested navigation in Xamarin shell)
As selector does his job, this DataTemplate will be selected as NavigationHeaderTemplate
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is ShellGroupItem && list.Contains(((ShellGroupItem)item).Title))
{
// Make sure a header item is not clickable.
((ShellGroupItem)item).IsEnabled = false;
return NavigationHeaderTemplate;
}
else
return NavigationItemTemplate;
}
So far, Selector only once check for each NavigationHeaderTemplate (as it should be), and for NavigationItemTemplate it checks every time visibility changes (as it should maybe be, its not quite optimal but it works properly)
After first tap on NavigationHeaderTemplate it only changes visibility of its items (thats correct) but after another tap it changes visibility and goes to AboutPage.
As you see in selection phase NavigationHeaderTemplate should be set as disabled
((ShellGroupItem)item).IsEnabled = false;
But somehow at second tap it goes to AboutPage.
<ShellContent Title="Header" ContentTemplate="{DataTemplate local:AboutPage}"/>
My question is:
How to prevent Header to load pages, it should only change visibility of items (items are used for links)
This doesn't work
<ShellContent Title="Header" ContentTemplate="{DataTemplate local:AboutPage}" IsEnabled="False"/>

After first tap on NavigationHeaderTemplate it only changes visibility of its items (thats correct) but after another tap it changes visibility and goes to AboutPage.
You can try to change FlyoutItemTemplateSelector by following code:
public class FlyoutItemTemplateSelector : DataTemplateSelector
{
public DataTemplate NavigationHeaderTemplate { get; set; }
public DataTemplate NavigationItemTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is ShellGroupItem && ((ShellGroupItem)item).Title == "Header")
{
// Make sure a header item is not clickable.
((ShellGroupItem)item).IsEnabled = false;
return NavigationHeaderTemplate;
}
else
return NavigationItemTemplate;
}
}
I tap the header one or more time, it just change visibility of its items.

Related

How to programatically scroll a ScrollViewer to the top in uwp xaml?

I have applied ScrollViewer to a user control which automatically scrolls to the bottom if height exceeds.
Now my page is closing having the scrollbar at the bottom position and it remains at the bottom when I reopen the page.
How can I reset the scrollbar to the top every time I open that page.
<ScrollViewer x:Name="myScrollViewer">
<Grid Margin="0,0,0,40">
</Grid>
</ScrollViewer>
ScrollViewer provides the ChangeView method, which can be used to adjust the scrolling state:
// scroll to top
myScrollViewer.ChangeView(0, 0, 1);
You can call this method after the page is loaded to scroll the ScrollViewer to the top.
Update
If you want to access the control on the page in the ViewModel, there are two ways:
1. Public control
This method means that you need to create a public page instance, and then expose the control in XAML, as shown below:
ScrollViewerPage.xaml
<ScrollViewer x:Name="myScrollViewer" x:FieldModifier="public">
<!-- your code -->
</ScrollViewer>
ScrollViewerPage.xaml.cs
public sealed partial class ScrollViewerPage : Page
{
public static ScrollViewerPage Current;
public ScrollViewerPage()
{
this.InitializeComponent();
Current = this;
}
}
After the page is loaded, you can use this code to access the ScrollViewer.
ScrollViewerPage.Current.myScrollViewer.ChangeView(0, 0, 1);
2. Define control variable/property in ViewModel
You can define a variable or property (public) of type ScrollViewer in the ViewModel, and then assign a value to the property when the page loads, and then you can access the ScrollViewer by accessing the property in the ViewModel.
MyViewModel.cs
public class MyViewModel
{
public ScrollViewer MyScrollViewer { get; set; }
// Other code
}
ScrollViewerPage.xaml.cs
public ScrollViewerPage()
{
this.InitializeComponent();
var vm = new MyViewModel();
vm.MyScrollViewer = myScrollViewer;
}

UWP navigation from child page frame to main page frame

I am developing an UWP app, I am getting an issue with back root frame navigation, I have main page in that I have frame, I navigate all pages into this frame ,, dashboard.xaml, orders.xaml....etc, I my orders.xaml I have another frame...in that frame I navigate 3 forms(xaml pages with a cancel button) when I hit cancel buton in any of those pages, I need to navigate to my orders page back... So I am facing problem with getting main page frame to navigate my Orders.xaml into that,,please help me. Thanks in advance
There are multiple ways to achieve what you want. For example, you can define a public static property in Mainpage that exposes the Frame.
public sealed partial class MainPage : Page
{
public static Frame MainPageFrame;
public MainPage()
{
this.InitializeComponent();
//Frame1 is the name of the Frame in XAML
MainPageFrame = Frame1;
}
...
}
And then in the order details page, use this property to navigate.
MainPage.MainPageFrame?.Navigate(typeof(Orders));
Or you can take advantage of VisualTreeHelper and get the parent Frame i.e "Frame1" like:
//this.Frame gets the Frame holds the order details page (i.e "Frame2")
FindParent<Frame>(this.Frame)?.Navigate(typeof(Orders));
The FindParent method here is a help method uses VisualTreeHelper.GetParent method like the following:
public static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parentObject = VisualTreeHelper.GetParent(dependencyObject);
if (parentObject == null) return null;
var parent = parentObject as T;
return parent ?? FindParent<T>(parentObject);
}
This should do it:
Frame.Navigate(typeof(orders));

FlipView SelectionChanged event occurs only when touch manipulations are complete

From the docs:
Note When a user flips through FlipView content using touch
interaction, a SelectionChanged event occurs only when touch
manipulations are complete. This means that when a user flips through
content quickly, individual SelectionChanged events are not always
generated for every item because the manipulation is still occurring.
Is there a way to configure the FlipView control to fire SelectionChanged for each flip? This behavior makes implementing paging interesting as the user, if flipping fast enough, can flip to the end of the list before more items can be added.
One solution to the problem is to extend the FlipView and monitor its ScrollViewer. Here is a quick sample of what I'm suggesting. Seems to work on horizontal flip view (haven't handled any other cases, and haven't tested too much).
public class FixedFlipView : FlipView {
public ScrollViewer ScrollViewer {
get;
private set;
}
protected override void OnApplyTemplate() {
base.OnApplyTemplate();
this.ScrollViewer = (ScrollViewer)this.GetTemplateChild("ScrollingHost");
this.ScrollViewer.ViewChanged += ScrollViewer_ViewChanged;
}
void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) {
var index = (int)this.ScrollViewer.HorizontalOffset - 2;
if (this.SelectedIndex != index) {
this.SelectedIndex = index;
}
}
}
Some things to note:
You may want to get the ScrollViewer in a different way that does not depend on its name. Like using the method in my answer here. Although, I'd guess this is fine, too.
It may be a better idea to use a separate event for this. In the code above I set the SelectedIndex property, which raises the SelectionChanged event, but it is also very likely to be doing other stuff as well, so it may be a problem in some cases.

Xpages partial refresh radio button

I have a radio button group with 2 values: Protected and Public.
I want to add the option that if protected selected: a field(laben:hidden) to be invisible, and if is public to be visible.
I have this code at the field visible property:
var protectie = getComponent("protect").getValue();
if(protect == "Public")
{ return true; }
if(protect == "Protected")
{ return false; }
and I have a partial refresh on the radio button goup, on onChange method.
It is working fine, but if I switch 2 times from protected to public I get the following error:
No element to submit with id view:_id1:_id2:_id31:hidden.
Thank you,
Florin
The error occurs because you want to refresh id "hidden" but it is not rendered at this time.
Frame your field/label with a panel. Partial refresh this panel ("panel1") but let the visible property in field/label.
<xp:panel id="panel1">
... your field/label ...
</xp:panel>

How to add clickhandler to the subrow of the celltablebuilder

I am able to build custom rows with celltablebuilder. When clicking on a particular anchor cell, I am able to build additional subrows for that row. This subrow has buttons, when clicking on the button I have do some action. I am able to add buttons with clickhandler in the subrow, but when clicking on the button nothing is happening clickhandler is not firing.
Can anybody please help.
protected void buildRowImpl(GridDTO rowValue, int absRowIndex ) {
buildRows(rowValue, absRowIndex, true);
if (showingFriends.contains(rowValue.getComponentId())) {
buildAdditonalRows( absRowIndex, gridDTO);
}
}
private void buildAdditonalRows(int index, GridDTO rowValue, ){
TableRowBuilder row = startRow();
td = row.startTD();
if(rowValue.getXpath() != null){
//td.text(rowValue.getXpath());
renderCell(td, createContext(1), cellTable.getColumn(1), rowValue);
}else{
td.text("");
}
td.endTD();
td = row.startTD();
Button button = new Button ();
button.setText("Save");
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("ssss");
}
});
DivBuilder div = td.startDiv();
div.html(new afeHtmlBuilder().appendHtmlConstant(button.toString()).toSafeHtml());
div.end();
td.endTD();
row.endTR();
}
CellPreviewEvent provides subindex. You can use it to get subrow value.
Example usage :
dataGrid.addCellPreviewHandler(new CellPreviewEvent.Handler<TreeItem>() {
#Override
public void onCellPreview(final CellPreviewEvent<TreeItem> event) {
if(event.getNativeEvent().getType().equals(BrowserEvents.CLICK)){
if(event.getContext().getSubIndex()>0){
event.getValue().getChild(event.getContext().getSubIndex()-1);
}
}
}
});
Or you can provide custom CellPreviewEvent.Handler implementation with selectionMode. For more details you can look at AbstractHasData
I had a similar situation where i needed a widget inside a cell to listen for click events... What i found out is that the widget doesn't respond to events once you inserted it into a cell (In other words, only the actual HTML that makes up for the widget gets put into the cell, any kind of event handling isn't included). The work around is to add the events to the Cell (You can make a custom cell class for that particular cell-widget and override OnBrowserEvent to listen for events.)
See GWT: On adding custom widget to celltable losing events of the custom widgets for a more eloquent explanation and example code.