I have the following animation set on a scrollviewer:
<ScrollViewer.Transitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</ScrollViewer.Transitions>
This brings me a nice animation where the scrollviewer (and it's content) enters from the right on the page load. But I have some content inside the scrollviewer which need some time to load from a database. I want to await this loading and then start the animation. How can I await the loading and trigger the animation on my own instead of on every page enter?
Related
I tried to get the same large title behavior like the settings app on iOS when the user scrolls down. The transition between the large title and the small title is smooth. But on Xamarin Forms the header snaps.
In my NavigationPage i set PrefersLargeTitles="true". In the embedded content page i set LargeTitleDisplay="Always" and UseSafeArea="true". The content in the page looks like this:
<ContentPage.Content>
<AbsoluteLayout>
<ListView />
<Frame x:Name="LoadingFrame" /> <!-- Only visible until ListView is loaded -->
</AbsoluteLayout>
</ContentPage.Content>
I tried setting NavigationPage.IsNavigationBarTranslucent="True". Then it works, but only if i disable SafeArea (Page.UseSafeArea="False") in the ContentPage. Disabling SafeArea is not what i want, because now the content is behind the notch.
I had the same issue.
The trick was to change top constraint of list to superView instead of safe area which only works on Native.
extendedLayoutIncludesOpaqueBars = true;
On Xamarin.Forms, I tried these solutions:
Use a custom renderer to set the LayoutConstraints of the scrollable view (Doesn't work)
Create a UITableViewController in a custom renderer then convert the Xamarin TableView element to a UITableView and set it to the TableView property of the UITableViewController then PushViewController to the new UITableViewController. (work)
You can raise the problem on github for better support:
https://github.com/xamarin/Xamarin.Forms/issues
I am using syncfusion controls for UWP. One of he feature I have seen in their sample application is showing the data grid on full page.
Something like this
After clicking on this the page looks like this
I am pretty sure that this is not full mode view of the app. After clicking on the button it hides the navigation drawer and the left panel as well.
Can someone please tell how it could be done?
Thanks in advance.
I don't know much about Syncfusion specifically, but I can describe how to implement it in general! This appears to be either a Navigation View or a Master/Details navigation design pattern (I linked both to thier respective documentation pages). Either way, the design pattern typically has the following structure:
Top Frame
Top Page
SplitView (or NavigationView)
Frame
Content Page
Content
Basically, the data grid normally sits on a page. That page is displayed in a frame that is in the content area of a SplitView or NavigationView, which is on the top-level page, which is displayed directly in the top-level frame in the app's window.
The "popping out" effect, that has the data grid display over the navigation drawer is likely some neat trickery going on with manipulating sub-pages, and the frames they are displayed in. So, lets take a look at how this effect can be implemented, given the above info about the structure of the navigation design pattern.
The data grid itself should be placed on its own page, which we will assume is called "DataGridPage" for the following code examples (note that the attributes for the page have been omitted for clarity):
<Page>
<!-- The data grid, or whatever content here -->
</Page>
We are actually adding two layers to the list presented above; the content page has a frame on it, and in that frame is a page with the data grid on it. So, your "content page" in the above list looks like this:
<Page>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition >
<RowDefinition Height="*"></RowDefinition >
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<!-- The bread-crumb, search box, and pop-out button are all in here -->
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<!-- The "left panel" here -->
</Grid>
<Frame Name="MyFrame"
Grid.Column="1"></Frame>
</Grid>
</Page>
And then in the constructor for your "content page" (I am assuming C#, but the logic is the same for VB):
public ContentPage()
{
this.InitializeComponent();
// You are telling the frame to display your page with the data grid on it.
// If you don't ever issue a different "Frame.Navigate" statement on this page,
// then it will statically display your data grid as if it was on the same
// page.
this.MyFrame.Navigate(typeof(DataGridPage));
}
Now, I don't know how the hamburger menu is implemented (the "navigation drawer"), and there are several ways to implement one, and I am guessing that it is a control that Syncfucsion provides for you... so I am going to skip trying to write out what the "Top Page" in the above list would look like (although I can detail one solution for implementing that without Syncfusion in a follow-up post if you would like). All that matters here, is that it has, somewhere on it, a frame that displays the "ContentPage" (which as detailed above contains the left panel and a display of your data grid page).
At the top level of the UWP app, the window your app is running in contains a single frame, which is itself displaying the "Top Page". This is important to note, as it is critical to how this "popping out" effect likely works.
On your "Content Page", handle the "Click" event of the "pop-out" button in the upper right of the page. In that event handler, you are going to take your data grid page, and display it in the top frame (the one directly inside of the app window) rather than the "Top Page" (which it is currently displaying).
The mechanics behind this are a little tricky, since you are handling an event on the "Content Page" (the click of the "pop-out" button), but you need to get a reference to the frame the parent page is displayed in (rather than the frame the content page is displayed in).
The solution is to write a custom event. The idea is that you fire this custom event whenever the "pop-out" button is clicked, and then the "top page" responds to the event, asking it's parent frame (the "top frame") to display the data grid page.
Here is a lengthy (and possibly overwhelming) overview of events. But the code you need looks something like the following. On your "Content page":
<!-- Other attributes omitted -->
<Button Name="PopOutButton"
Click="PopOutButton_Click">
And then in the code of the "Content page":
public sealed partial class ContentPage : Page
{
// This is the declaration for your custom event.
public delegate void PopOutRequestedHandler(object sender, PopOutRequestedEventArgs e);
public event PopOutRequestedHandler PopOutRequested;
private void RequestPopOut()
{
// Ensure that something is listening to the event.
if (this.PopOutRequested!= null)
{
// Create the args, and call the listening event handlers.
PopOutRequestedEventArgs args = new PopOutRequestedEventArgs();
this.PopOutRequested(this, args);
}
}
public void PopOutButton_Click(object sender, RoutedEventArgs e)
{
// Any animation logic you want goes here.
this.RequestPopOut();
}
}
You can define a class PopOutRequestedEventArgs to include whatever properties you want to pass in your event. None are strictly necessary for the basic implementation.
Now, on your "Top Page", you need to subscribe to the event. Do so in the "Navigated" event handler for the frame on the top page. So you have this somewhere on your top page:
<Frame Name="NavFrame"
Navigated="NavFrame_Navigated"></Frame>
Then in your "Top page" code, you have:
private void NavFrame_Navigated(object sender, NavigationEventArgs e)
{
if (e.Content is ContentPage page)
{
page.PopOutRequested += this.ContentPage_RequestedPopOut;
}
}
private void ContentPage_RequestedPopOut(object sender, PopOutRequestedEventArgs e)
{
// This tells the frame this page (the "Top Page") is in, to
// instead display the data grid page.
this.Frame.Navigate(typeof(DataGridPage));
}
That is the effect, in a nutshell. To get the page to "close" again, simply put a button on your datagrid page (which you can hide when the page is displayed in the frame on the "Content page"), and handle its Click event. In that event, request the frame navigate back to the "Content page". So, on your data grid page somewhere, you have the same button as detailed above on the "Content page", and in its event handler you put:
this.Frame.Navigate(typeof(ContentPage));
Now, it is important that you ONLY allow the button to be clicked when the "data grid page" is displayed in the "top frame", as that code references the frame the page is displayed in when it is run... it is not an absolute reference. You will get some unexpected results if you call that code while the "data grid page" is displayed in the frame on the "Content page".
As for restoring the state of the "Top page" when you navigate back to it when closing out of the "popped out" view of the data grid, you can accomplish that via the "NavigationEventArgs". Store the state of the "Top page" (such as the fact that the frame on it is displaying the "Content page") in your own class (we will call it "NavArgs" here), and then pass that as a parameter in the Navigate statements:
// Create an instance of the args class, and store your state info.
NavArgs navArgs = new NavArgs();
this.Frame.Navigate(typeof(DataGridPage), navArgs);
You can store the "navArgs" on your data grid page, and then when exiting out of the "popped out" view, and navigating back to the "Top page" in the "top frame", similarly pass them through the Frame.Navigate() call.
It's a little thorough (although still glosses over a lot of concepts), and it is only one possible way to implement that functionality, but hopefully it helps!
You can show the grid in full page by using the property GridColumnSizer.Star .
In GridColumnSizer.Star type, the available grid width is divided into equal sized regions and the divided width is set for each column. When you have three columns in the grid, the total space is divided by three and that value is allocated to the width of the column.
You can get more details about ColumnSizing from the below links.
https://help.syncfusion.com/uwp/sfdatagrid/columns#column-sizing
Regards,
Sathiyathanam
I created an Image Button and put a Tap Gesture into it. I want my Image Button to call another Page but I don't know how am I going to do that without using Navigation.PushAsync but it's causing me this error "PushAsync is not supported globally on Android, please use a Navigation Page."
This is my XAML code.
<Image Source="add.jpg">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="TapGestureRecognizer_OnTapped"
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
and this is my XAML.CS code.
private void TapGestureRecognizer_OnTapped(SecondPage secondPage)
{
Navigation.PushAsync(new SecondPage());
}
If you need to use PushAsync, the parent Page should be a NavigationPage.When we use NavigationPage and do PushAsync the Navigation stack will be maintained and you will get a back button in Actionbar for back navigation.
Rather if we use PushModalAsync, the page will be presented modally.
Changing PushAsync to PushModalAsync will work.
private void TapGestureRecognizer_OnTapped(SecondPage secondPage)
{
Navigation. PushModalAsync(new SecondPage());
}
Simpel question, I have a windows phone page that contains a scrollviewer with inside it an image, a textblock and a richtextbox.
Now when the user starts scrolling I want to keep the textblock in view on top when the image has scrolled outside the page.
So the effect is, user starts scrolling upwards, everything scrolls upwards, when the image is outside the page, the textblock stays at the top of the page but the richtextbox keeps scrolling upwards.
Any thoughts?
Here is a way to reach this result:
First, the layout. I've set a grid, with two rows. The first is empty, and will host the header when we need to freeze it. The second row contains the scrollviewer.
Inside the scrollviewer, I've put the controls in a grid, but you can use whatever container suits you.
<ScrollViewer Grid.Row="1"
Margin="0"
Padding="0"
x:Name="ParentScroll"
ManipulationMode="Control"
MouseMove="ParentScroll_MouseMove">
<Grid x:Name="ChildGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Image Source="Picture.jpg" Grid.Row="0"/>
<TextBlock Text="Header" Grid.Row="1" x:Name="TextHeader" />
<RichTextBox Grid.Row="2" x:Name="RichText">
<Paragraph>
<Bold>RichTextBox</Bold>
<!-- More stuff -->
</Paragraph>
</RichTextBox>
</Grid>
</ScrollViewer>
I use the MouseMove event to be notified of the scrolling event. You can also dig into the template, extract the ScrollBar control, and subscribe to the ValueChanged event, as described here: http://social.msdn.microsoft.com/Forums/wpapps/en-US/81fcd34e-6ec9-48d0-891e-c53a53344553/scrollviewer-synchronization
Note that you need to set ManipulationMode to Control or the position of the controls won't be updated at a smooth rate. I guess it's due to some internal optimization.
In the code behind, I use the TransformToVisual method to compute the relative position of the controls to the ScrollViewer. This way, I can know when the header goes out of view. When it does, I remove it from the child grid, and put it outside of the ScrollViewer, in the parent grid. When the top of the RichTextBox goes out of view, I put the header back into the ScrollViewer:
private void ParentScroll_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (Grid.GetRow(this.TextHeader) == 1)
{
var generalTransform = TextHeader.TransformToVisual(ParentScroll);
var childToParentCoordinates = generalTransform.Transform(new Point(0, 0));
if (childToParentCoordinates.Y < 0)
{
this.ChildGrid.Children.Remove(this.TextHeader);
this.ParentGrid.Children.Add(this.TextHeader);
Grid.SetRow(this.TextHeader, 0);
}
}
else
{
var generalTransform = RichText.TransformToVisual(ParentScroll);
var childToParentCoordinates = generalTransform.Transform(new Point(0, 0));
if (childToParentCoordinates.Y > 0)
{
this.ParentGrid.Children.Remove(this.TextHeader);
this.ChildGrid.Children.Add(this.TextHeader);
Grid.SetRow(this.TextHeader, 1);
}
}
There may be less-hacky ways to reach the same results, but this solution seems to work smoothly in the emulator.
I've found a working solution myself... the complete detail is available on my blog here... it contains also the link to my demo project on GitHub.
The trick was to get hold of the VerticallScrollBar inside the ScrollViewer and to set the ManipulationMode to Control to get enough feedback on the UI thread.
With the scroll offset information of the scrollbar we than animate the specific ui element we want to keep in view.
I am writing a Windows Store app using C++/XAML with DirectX interop - SwapChainBackgroundPanel.
The application is based on the template "Split Page". From each list view item, a DirectX page may be launched using code below.
Window::Current->Content = ref new MyD3Components::DirectXPage();
Window::Current->Activate();
This is working fine and DirectX page opens up and plays very well.
What I would like to have a button in the app bar which helps user to go back and display the "Split Page" to allow selecting another DirectX page. This I have not been able to accomplish yet.
Among several things I have tried, below is the most logical one to my opinion. It gives a "Platform::DisconnectedException" when user wants to go back to the last page.
Windows::UI::Xaml::Controls::Frame^ rootFrame = SDL::App::GetRootFrame();
Window::Current->Content = rootFrame;
Window::Current->Activate();
Please look to see if you have a suggestion or better a solution.
Here the sample example for your question :
What i am creating : 2 pages...
You will have (go to page 2)link on page 1...If u click that,the second page should appear that says "Page 2" at the top. Notice that there is a back button to the left of the page title. Click the button to return to the first page...
1.) Find the TextBlock element named pageTitle and change the Text property to Page 1. The XAML should look like this:
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="Page 1"
Style="{StaticResource PageHeaderTextStyle}"/>
2.)Add the following XAML as a second child element to the root Grid. The StackPanel element should be a sibling to the Grid that contains the back button and page title.
<StackPanel Grid.Row="1"
Margin="120,0,120,60">
<HyperlinkButton Content="Click to go to page 2" Click="HyperlinkButton_Click_1"/>
</StackPanel>
3.)Make the following changes to BasicPage2.xaml.
Find the TextBlock element named pageTitle and change the Text property to Page 2. The XAML should look like this:
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="Page 2"
Style="{StaticResource PageHeaderTextStyle}"/>
4.)Add the following XAML as a second child element to the root Grid. The StackPanel element should be a sibling to the Grid that contains the back button and page title.
<StackPanel Grid.Row="1"
Margin="120,0,120,60">
<TextBlock HorizontalAlignment="Left" Name="tb1" Text="Hello World!"/>
</StackPanel>
5.)Add the following code to the BasicPage1 class in BasicPage1.Xaml.cs
private void HyperlinkButton_Click_1(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(BasicPage2));
}
6.)Now that we've prepared the new pages, we need to make BasicPage1 the first thing that appears when the app starts. Open app.xaml.cs and change the OnLaunched method to call Frame.Navigate by using BasicPage1 instead of the BlankPage. The entire OnLaunched method should look like the following:
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
// Create a Frame to act navigation context and navigate to the first page
var rootFrame = new Frame();
rootFrame.Navigate(typeof(BasicPage1));
// Place the frame in the current window and ensure that it is active
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
Now you are ready to test the app. Start the app, and click the link that says Click to go to page 2. The second page should appear that says "Page 2" at the top. Notice that there is a back button to the left of the page title. Click the button to return to the first page.
Thats it! hope it helps u.
After a bit of trial and error, I am in the position to answer my own question. It seems that all I needed to do was to remove my rendering callbackfrom the CompositionTarget.
It was added like below.
m_eventToken = CompositionTarget::Rendering::add(ref new Windows::Foundation::EventHandler<Object^>(this, &DirectXPage::OnRendering));
Before replacing the current window and activating it, I called below.
CompositionTarget::Rendering::remove(m_eventToken);
I guessed this helped DirectX not to output to rendering pipeline and complain (disconnectedexception) when the target is not there.