The question is, when a XAML page is used inside another XAML page, how can I load saved states of both pages?
Details
To make my ProfilePage.xaml simple and reusable, I've created it separately and use it inside pivot of the MainPage.xaml (is that a good approach?)
<Grid>
<Pivot>
<PivotItem>
<Grid/>
</PivotItem>
<PivotItem>
<Frame x:Name="ProfileFrame"/>
</PivotItem>
</Pivot>
</Grid>
When MainPage is loaded, ProfileFrame navigates to ProfilePage.xaml:
this.ProfileFrame.Navigate(typeof(ProfilePage), parameter);
Each page saves state normally using NavigationHelper
private void NavigationHelper_SaveState(object sender, SaveStateEventArgs e)
{
e.PageState["collection"] = collection;
}
The problem is that the MainPage saves state, and then when come back again to the MainPage, ProfilePage needs to be created new, without loading the old saved data.
How can I load state of ProfilePage.xaml when it is used inside frame control of the MainPage.xaml?
Related
I am working on a UWP app and encountered an issue with the background image changing when I navigate to different pages.
In my RootPage.xaml file I have this layout
<Grid x:Name="Root">
<Grid.Background>
<ImageBrush
ImageSource="{Binding ImageSource}"
Stretch="UniformToFill" />
</Grid.Background>
<SplitView Name="Splitter" IsPaneOpen="False" DisplayMode="Overlay" PaneBackground="Transparent">
<SplitView.Pane>
<Grid>
<!-- list view -->
</Grid>
</SplitView.Pane>
<Frame Name="MainFrame"></Frame>
</SplitView>
</Grid>
In my code behind I handle changes in the selection changed event like so
private void SectionList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// code to get the navigation item page the event args
// then navigate like so
MainFrame.Navigate(item.DestinationPage);
}
But when I navigate to the one of the other pages my background image that was set on the grid is lost. It just turns black.
I am missing something here, I have been watching a ton of tutorials but must have missed something. I just want the page content where frame is, and replace that depending on where the user navigated to. But leave the split view navigation stuff to live on every page.
Once you navigate to your "DestinationPage" you will see whatever background is set on the root element of that page (default is: {ThemeResource ApplicationPageBackgroundThemeBrush} ).
If you want the page to be transparent, so that the user will see the background image of the root Grid, you can set Background="Transparent" on your page's root element.
Hope this helps - thanks!
Stefan Wick
I'm porting an iOS app to a UWP project and there is something I'd love to do to save a bit of repetition but not sure how to do it.
On iOS I would embed a UINavigationController inside a UIContainerView and be able to push/pop only a section of the screen instead of pushing a full page on top of another.
Is there any way to do something similar on a UWP project? I effectively want to have a Page within a Page, and on the Inner page, be able to push a new page on top of that page.
Example: Have 3 navigation buttons along the top of the page. They are 'Tabs' which load 1 page per button into the area below it. It's a highly customised TabBar. The buttons would be nice to have in their own page with the content for each 3 pages in it's own page.
Currently I'm, doing this by either re-using the buttons along the top in multiple pages. Or I can swap out multiple UserControls manually based on which button is pressed. One UserControl for each page.
Any help on the preferred method for this would be grand!
Cheers,
Dave.
Is there any way to do something similar on a UWP project? I effectively want to have a Page within a Page
If I didn't understand it wrong, you can use Frame.
For Example: On MainPage.Xaml you can define one Frame with three Buttons:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Button Name="btnPageOne" Content="Page One" Click="btnPageOne_Click"></Button>
<Button Name="btnPageTwo" Content="Page Two" Click="btnPageTwo_Click"></Button>
<Button Name="btnPageThree" Content="Page Three" Click="btnPageThree_Click"></Button>
<Frame Name="MyFrame" Width="500" Height="600"></Frame>
</StackPanel>
</Grid>
And on the click events of three buttons you can navigate the Frame to three pages:
private void btnPageOne_Click(object sender, RoutedEventArgs e)
{
MyFrame.Navigate(typeof(PageOne));
}
private void btnPageTwo_Click(object sender, RoutedEventArgs e)
{
MyFrame.Navigate(typeof(PageTwo));
}
private void btnPageThree_Click(object sender, RoutedEventArgs e)
{
MyFrame.Navigate(typeof(PageThree));
}
and on the Inner page, be able to push a new page on top of that page.
You can define a button on PageOne inside a StackPanel like below:
<Grid Name="rootGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Name="myStackPanel">
<Button Name="myBtn" Click="myBtn_Click">Click Me to add Page</Button>
</StackPanel>
</Grid>
And in the Click event add new Frames to that StackPanel:
private void myBtn_Click(object sender, RoutedEventArgs e)
{
Frame newFrame = new Frame{
Width=100,
Height=100
};
myStackPanel.Children.Add(newFrame);
newFrame.Navigate(typeof(SubPageOne));
}
Here is the basic Demo that I made: FrameNavigationSample
Whilst using the InkCanvas in an app I'm currently developing I found after moving between pages that had InkCanvases on them the app would crash with a Xaml Parse Exception. It seemed random, however I created a simple app to get rid of as many variables that could be causing this. I added 2 pages to move between with multiple (10) InkCanvases on the second page. The app consistently crashes after moving back and forth between the pages 10 or more times. Below I have added my simple test pages.
Page 1:
<Page>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button Content="Navigate"
Click="ButtonBase_OnClick"/>
</Grid>
</Page>
Page 1 Code behind:
public sealed partial class MainPage : Page {
private Frame rootFrame;
public MainPage() {
this.InitializeComponent();
rootFrame = Window.Current.Content as Frame;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
rootFrame.Navigate(typeof (PageTwo));
}
}
Page 2:
<Page>
<StackPanel>
<TextBlock Text="Sign 1"/>
<InkCanvas Width="100"
Height="100"/>
<TextBlock Text="Sign 2"/>
<InkCanvas Width="100"
Height="100"/>
<!-- Another 8 InkCanvases -->
</StackPanel>
</Page>
I checked the memory profiler to see if the InkCanvases or pages were being held onto in memory but from what I could see they weren't.
Has anyone else experienced this issue? Or is there any known workaround?
Just set the NavigationCacheMode of pagetwo to Required or Enabled as follows:
public Page2()
{
this.NavigationCacheMode = NavigationCacheMode.Required;
this.InitializeComponent();
}
I have tested your code , navigate to pagetwo from pageoneand then navigate from pagetwo to pageone , after about thirteen rounds, the app crashes and throw the exception:
Cannot create instance of type 'Windows.UI.Xaml.Controls.InkCanvas'
So it seems the instance size of InkCanvas for the frame is exceeded. Every time you navigate you will create ten instances for the InkCanvas. So we set the NavigationCacheMode to require , it means
The page is cached and the cached instance is reused for every visit regardless of the cache size for the frame.
You also can set it to Enabled.It depends on your requirements.
More details about instance cache, please see NavigationCacheMode
I am setting the GridView Data Context in XAML similar to so:
<Grid x:Name="pageGrid">
<Grid.DataContext>
<local:ViewModel/>
</Grid.DataContext>
</Grid>
This "ViewModel" class is a static class that is fill during:
public MainPage()
{
this.InitializeComponent();
FillViewModel():
}
This allows for the view model to bound on screen load which works.
However, I want to load FillViewModel after the MainPage has initially ran.
Is there a way to programatically refresh the pageGrid XAML databinding? I have to be just missing it.
However, I want to load FillViewModel after the MainPage has initially ran.
Sounds like your looking for the MainWindow / Control "Loaded" Event.
XAML:
<Grid x:Name="Grid1" Loaded="Grid1_Loaded"/>
Code Behind:
private void Grid1_Loaded(object sender, RoutedEventArgs e)
{
// Do Stuff
}
I need to send a string(TextBlockName.Text) from usercontrol to application page after clicking on the button.
Application page XAML:
<ListBox x:Name="lstFlags">
<ListBox.ItemTemplate>
<DataTemplate>
<local:ListItem />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
UserControl "ListItem" с# code:
public partial class ListItem : UserControl
{
...
private void Button_Click(object sender, RoutedEventArgs e)
{
}
}
User control Xaml:
<Button Click="Button_Click">
<TextBlock Name="TextBlockName" Text="{Binding ShortName}" />
</Button>
So. I think it is necessary to generate event in application page when button clicked. How can I do this?
I think what you're trying to ask here is how you can send the textblock1.Text (for example) value to the code behind.
By the looks of it, you're using Data Binding to bind the data, but you also have a Button_Click event.
Generally I use one or the other (unless i'm doing something complex), if you simply want to get the Text value form the TextBlock, then you can either do:
<TextBlock Name="textBlockName" Text="{Binding ShortName}" Mode="TwoWay">
The Mode="TwoWay" ensures that the value of the Text Block gets sent to and from the code-behind object, in this case calledShortNameand to theTextBlock.Text`.
The other method is to simply create a Button click event which you already seem to have. In the Button Click event, simply do the following:
string myString = textBlock1.Text;
As you can guess, that simply gets the string value that's within the Text property of the textBlock and puts it inside the myString object.
But - as an important note, you should try to elaborate as much as possible to ensure that people who are viewing your question understand and can help you.