UWP Navigation Pane go back button not working - c#

I'm learning UWP and trying to implement GO BACK button in a navigation pane. I put go-back button under a RelativePanel right below menu button. The below is my current XAML page:
<Page
x:Class="LearningUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Windows.UI.Xaml.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<RelativePanel>
<Button Name="Menu" FontFamily="Segoe MDL2 Assets" Content="" FontSize="36" Click="Menu_Click"></Button>
<Button RelativePanel.Below="Menu" Style="{StaticResource NavigationBackButtonNormalStyle}" Name="Back" FontSize="36" Click="Back_Click"></Button>
</RelativePanel>
<SplitView Name="MySplitView"
Grid.Row="1"
DisplayMode="CompactOverlay"
OpenPaneLength="200"
CompactPaneLength="56"
HorizontalAlignment="Left">
<SplitView.Pane>
<ListBox SelectionMode="Single"
Name="IconsListBox"
SelectionChanged="IconsListBox_SelectionChanged"
>
<ListBoxItem Name="ShareListBoxItem">
<StackPanel Orientation="Horizontal" >
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="36" Text=""/>
<TextBlock Text="Share" FontSize="24" Margin="20, 0, 0, 0"/>
</StackPanel>
</ListBoxItem>
<ListBoxItem Name="FavoritesListBoxItem" >
<StackPanel Orientation="Horizontal" >
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="36" Text=""/>
<TextBlock Text="Favorites" FontSize="24" Margin="20, 0, 0, 0"/>
</StackPanel>
</ListBoxItem>
</ListBox>
</SplitView.Pane>
<SplitView.Content>
<TextBlock Margin="50, 0, 0, 0" Name="ResultTextBlock"/>
</SplitView.Content>
</SplitView>
</Grid>
</Page>
And the XAML's code-behind:
namespace LearningUWP
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Menu_Click(object sender, RoutedEventArgs e)
{
MySplitView.IsPaneOpen = !MySplitView.IsPaneOpen;
}
private void IconsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ShareListBoxItem.IsSelected)
ResultTextBlock.Text = "shared";
else if (FavoritesListBoxItem.IsSelected)
ResultTextBlock.Text = "Favorites";
}
private void Back_Click(object sender, RoutedEventArgs e)
{
if (this.Frame.CanGoBack)
this.Frame.GoBack();
}}}
For some reason, after I click the Go back button, it doesn't work as expected, and what is more, I find this.Frame.CanGoBack = false.
How to solve it?

From the code that you have posted we can see that this.Frame is actually the refering to the root frame of the application, which at the moment has only navigated to a single page (MainPage) (As defined in your App.xaml.cs). Thus there is no page that it can go back to (this.Frame.CanGoBack = false).
A little in depth explanation :
If you go into App.xaml.cs file in your project, in the OnLaunched() method you will find the following code :
rootFrame.Navigate(typeof(MainPage), e.Arguments);
Here the application, after launch will navigate the rootFrame to the MainPage.
When you use this.Frame from your MainPage it actually refers to the rootFrame, which at this moment has only navigated to the MainPage, thus it does not have any page that it can go back to , hence this.Frame.CanGoBack = false.
Solution :
When you use a SplitView, in the content you should specify a Frame which you can use to navigate between different pages . Thus your app will look something like this :
Here Red rectangle is used to show the rootFrame where as Blue is used to show the Frame which you have to define in your SplitView content.
For this, you need to make minor modifications to your code something like this :
XAML
<Page
.....
.....
<SplitView Name="MySplitView"
.....>
<SplitView.Pane>
.....
</SplitView.Pane>
<SplitView.Content>
<Frame x:Name="appFrame"></Frame>
</SplitView.Content>
</SplitView>
</Page>
C#
private void IconsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ShareListBoxItem.IsSelected)
appFrame.Navigate(typeof(page1));//navigating to page1
else if (FavoritesListBoxItem.IsSelected)
appFrame.Navigate(typeof(page2));//navigating to page2
}
private void Back_Click(object sender, RoutedEventArgs e)
{
if (appFrame.CanGoBack)
appFrame.GoBack();
}
Hope this helps..!

Related

Scroll to object on Button click (C# /Xaml)

Is there a way to have a xaml page scroll to a particular object on a button click? For example, I have three buttons at the top of my page. I would like each button to move the scrollviewer to the top, middle, and bottom section of the page. How can I make this happen? Thanks!
I try to create the Xaml and to solve the problem. This is my solution.
This is the Xaml code.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button HorizontalAlignment="Left" Content="Top" Click="Button_Click" ></Button>
<Button HorizontalAlignment="Center" Content="Center" Click="Button_Click_1" ></Button><Button Content="Botton" HorizontalAlignment="Right" Click="Button_Click_2" ></Button>
<ScrollViewer Grid.Row="1" Name="MyScrollViewer" MaxZoomFactor="9">
<StackPanel>
<TextBlock Name="TextBlock" Height="20"> </TextBlock>
<Rectangle Height="300" Width="100" Fill="BlanchedAlmond"></Rectangle>
<Rectangle Height="300" Width="100" Fill="Blue"></Rectangle>
<Rectangle Height="300" Width="100" Fill="BlueViolet"></Rectangle>
<Rectangle Height="300" Width="100" Fill="Chartreuse"></Rectangle>
<Rectangle Height="300" Width="100" Fill="Crimson"></Rectangle>
</StackPanel>
</ScrollViewer>
</Grid>
And this is the .cs Code
private void Button_Click(object sender, RoutedEventArgs e)
{
MyScrollViewer.ScrollToVerticalOffset(0);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
var scrollableHeight = MyScrollViewer.ScrollableHeight;
var height= scrollableHeight / 2;
MyScrollViewer.ScrollToVerticalOffset(height);
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
MyScrollViewer.ScrollToVerticalOffset(MaxHeight);
}
}

Hide/Display XAML elements or block LostFocus event

I have a page containing two StackPanels, each containing one TextBox and one Button:
<StackPanel x:Name="Row1">
<TextBox x:Name="TextBox1" Text="" GotFocus="OnFocusHandler" LostFocus="OffFocusHandler"/>
<Button x:Name="Button1" Content="Convert" Click="OnClickHandler" Visibility="Collapsed"/>
</StackPanel>
<StackPanel x:Name="Row2">
<TextBox x:Name="TextBox2" Text="" GotFocus="OnFocusHandler" LostFocus="OffFocusHandler"/>
<Button x:Name="Button2" Content="Convert" Click="OnClickHandler" Visibility="Collapsed"/>
</StackPanel>
I would like to do the following:
When a textbox has focus, the other textbox must be hidden and the corresponding button must show
When a textbox is out of focus, we are back to the original display: only empty textboxes are visible
I don't want the button to be able to trigger the OffFocusHandler
This is the current code that I have for the three handlers:
private void OnFocusHandler(object sender, RoutedEventArgs e)
{
TextBox SenderTextBox = (TextBox)sender;
if (SenderPanel.Name == "TextBox1")
{
Button1.Visibility = Visibility.Visible;
}
else if (SenderPanel.Name == "TextBox2")
{
Button2.Visibility = Visibility.Visible;
}
}
private void OffFocusHandler(object sender, RoutedEventArgs e)
{
TextBox1.Text = "";
TextBox2.Text = "";
Button1.Visibility = Visibility.Collapsed;
Button2.Visibility = Visibility.Collapsed;
}
private void OnClickHandler(object sender, RoutedEventArgs e)
{
// some stuff unrelated to my issue
}
How do I avoid the button clicking to trigger the OffFocusHandler code?
Is there another way to code this? I'm a complete beginner so I may not think the right way.
You can just Bind to the TextBox.IsFocused property in Xaml, and use the BooleanToVisibilityConverter to show/hide the button.
Example:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication4"
Title="MainWindow" Height="300" Width="400" Name="UI" >
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolTovisible" />
</Window.Resources>
<Grid>
<StackPanel x:Name="Row1" Height="54" VerticalAlignment="Top">
<TextBox x:Name="TextBox1" Text="" />
<Button x:Name="Button1" Content="Convert" Visibility="{Binding ElementName=TextBox1, Path=IsFocused, Converter={StaticResource BoolTovisible}}"/>
</StackPanel>
<StackPanel x:Name="Row2" Margin="0,60,0,0" Height="51" VerticalAlignment="Top">
<TextBox x:Name="TextBox2" Text="" />
<Button x:Name="Button2" Content="Convert" Visibility="{Binding ElementName=TextBox2, Path=IsFocused, Converter={StaticResource BoolTovisible}}"/>
</StackPanel>
</Grid>
</Window>
for each element, there is a Visibility tag, it is "Visible" by default but you can assign "Hidden" or "Collapsed" as follow:
<RadioButton Margin="20,118,318,-43" GroupName="MCSites" Visibility="Hidden">
Radio Button Description
</RadioButton>

XamlParseException in windows Phone Application

I am trying to create my first Windows phone application but I keep getting this "XamlParseException" thrown at me.It looks like the error is coming from the InitializeComponent() method which is a shock because it was automatically created by VS.
Here is the Exception :
XamlParseException
Failed to assign to property 'System.Windows.FrameworkElement.Loaded'. [Line: 14 Position: 39]
Here is the code behind :
namespace WinHomeWork1
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void PhoneApplicationPage_Loaded(object sender, TextChangedEventArgs e)
{
myTextBox.Focus();
}
private void ClickMe_Click(object sender, RoutedEventArgs e)
{
if (myTextBox.Text.CompareTo("1 2 3 4") == 0)
{
myTextBlock.Text = "You have won!";
}
else
myTextBlock.Text = "You have Lost";
}
}
}
Here is the Xaml Code :
<phone:PhoneApplicationPage
x:Class="WinHomeWork1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True" Loaded="PhoneApplicationPage_Loaded">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="Brahman Initiative" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="108 mintes" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBox Height="72" HorizontalAlignment="Left" Margin="0,6,0,0" Name="myTextBox" Text="" VerticalAlignment="Top" Width="460" />
<Button Content="Go" Height="74" HorizontalAlignment="Left" Margin="234,88,0,0" Name="ClickMe" VerticalAlignment="Top" Width="222" Click="ClickMe_Click" />
<TextBlock Height="68" HorizontalAlignment="Left" Margin="12,88,0,0" Name="myTextBlock" Text="" VerticalAlignment="Top" Width="200" />
</Grid>
</Grid>
<!--Sample code showing usage of ApplicationBar-->
<!--<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="MenuItem 1"/>
<shell:ApplicationBarMenuItem Text="MenuItem 2"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>-->
</phone:PhoneApplicationPage>
The program has only 3 elements, 1) A TextBox 2) A TextBlock and a 3) Button. The user inputs data into the textBox then clicks a "Go" button, if the input is "1 2 3 4" the app will display "You have Won" in the textBlock, if any other input has been entered it will display " You have lost".Please Help, I do not know any Xaml so I can't play around with the Xaml code.
Change the parameter e in your PhoneApplicationPage_Loaded to an instance of the RoutedEventArgs class:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
myTextBox.Focus();
}
Your error is due to PhoneApplicationPage_Loaded event handler method. It should be like this:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
myTextBox.Focus();
}

creating multiple panels and displaying one panel on button click in wpf

I am new to WPF and I want to create a WPF application with 5buttons. On the click of each button I want a content to be displayed on another panel. Right now I just want different images to be displayed on my right side panel on the button clicks.
Here's my XAML code:
<Window x:Class="GridButton.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MyFirstApp" Height="350" Width="525" Loaded="Window_Loaded">
<Viewbox Stretch="Fill" StretchDirection="Both">
<DockPanel>
<StackPanel DockPanel.Dock="left" Margin="5" Width="Auto" VerticalAlignment="Center" Height="Auto">
<Button Content="1" Name="button2" Click="button2_Click">
</Button>
<Button Content="2" Name="button1" Click="button1_Click_1">
</Button>
<Button Content="3" Name="button3" Click="button3_Click">
</Button>
<Button Content="4" Name="button4" Margin="5">
</Button>
<Button Content="5" Name="button5" Margin="5" Click="button5_Click_1">
</Button>
</StackPanel>
<StackPanel DockPanel.Dock="Right">
<Image Name="img1" Source="Blue Hills.jpg" Stretch="Uniform" Visibility="Hidden" ImageFailed="Image_ImageFailed" Height="257" />
</StackPanel>
</DockPanel>
And my xaml.cs file contains code to display image:
private void button2_Click(object sender, RoutedEventArgs e)
{
img1.Visibility = Visibility.Visible;
}
I could get only this far.
You can set the Source property of the Image control in code:
private void buttonx_Click(object sender, RoutedEventArgs e)
{
string path = ... // path to image file here
img1.Source = new BitmapImage(new Uri(path));
}
You could easily reuse the same Click handler for all Buttons and check which one was pressed:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
string path = null;
if (button == button1)
{
path = ... // path to image file 1 here
}
else if ...
if (path != null)
{
img1.Source = new BitmapImage(new Uri(path));
}
}
If you want to remove the a child Panel (or other control) from a parent Panel and add another one, you would have to modify the Panel's Children property:
<StackPanel Name="parent">
<StackPanel Name="child" />
</StackPanel>
parent.Children.Remove(child);
parent.Children.Add(...); // some other control here
This approach would usually make sense if you wanted to create child panels dynamically. If you want to declare everything in XAML you may put all child panels in a Grid and change their visibility as you did already.
However, you might also change the ZIndex attached property.
<Grid>
<StackPanel Name="child1">
</StackPanel>
<StackPanel Name="child2">
</StackPanel>
<StackPanel Name="child3">
</StackPanel>
</Grid>
child3 is topmost by default, but now you can set ZIndex to some value > 0 to make another child topmost:
private void Button_Click(object sender, RoutedEventArgs e)
{
...
// reset ZIndex on previous topmost panel to 0 before
Panel.SetZIndex(child1, 1);
}
Or completely omit the Button/Grid/Panel design and use a TabControl.

SelectionChanged Event for ListBox. Pass parameters between pages

I am building a WP7 app that consist on one listbox in the first page to show the id of several task and a detail page to show the details for each task (selected).
I need to pass the task id from the first page to the second one. I know that it is carried out by SelectionChanged event of the listbox.
This is my XAML code:
<phone:PhoneApplicationPage
x:Class="TaskListAlpha03.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls">
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="TaskListListBoxTemplate">
<StackPanel Orientation="Vertical" Margin="0,0,0,20">
<TextBlock Text="{Binding Crm_object_id}" FontSize="32" FontFamily="Segoe WP Bold" Foreground="Gray"/>
<!--<TextBlock Text="{Binding Comment}" Margin="10,0,0,0"/> -->
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,40">
<TextBlock x:Name="ApplicationTitle" Text="TASK LIST ALPHA" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="tasks" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox
x:Name="allTaskListTasksListBox"
ItemsSource="{Binding AllTaskListTasks}"
ItemTemplate="{StaticResource TaskListListBoxTemplate}"
SelectionChanged="allTaskListTasksListBox_SelectionChanged" />
</Grid>
</Grid>
</phone:PhoneApplicationPage>
And this is the cs code:
private void allTaskListTasksListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
NavigationService.Navigate(new Uri("/View/Details.xaml?msg=" + lbi.Content.ToString(), UriKind.RelativeOrAbsolute));
}
In the second page I have this sample code to check if it works:
protected override void OnNavigatedTo
(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string msg = "";
if (NavigationContext.QueryString.TryGetValue("msg", out msg))
PageTitle.Text = msg;
}
When I execute the application I have a "NullReferenceException".
Sorry for my english :S and thanks.
A couple of points here...
1) I would use a Tap event on the item rather than a selection changed event. It helps prevent accidental navigation.
2) If you do use the selectionchanged event, try the following code to get your item. Your current code will attempt to fire if an items is de-selected in the list.
private void allTaskListTasksListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(e.AddedItems.Count > 0) // the items that were added to the "selected" collection
{
var mySelectedItem = e.AddedItems[0] as myItemType;
if(null != mySelectedItem) // prevents errors if casting fails
{
NavigationService.Navigate(
new Uri("/View/Details.xaml?msg=" + mySelectedItem.Crm_object_id,
UriKind.RelativeOrAbsolute)
);
}
}
}
The problem is with ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);. You are casting it to ListBoxItem which in fact it is your custom item you bind it to the ListBox. Do something like:
var item = ((sender as ListBox).SelectedItem as YourItem);

Categories