Consider me a very beginner App developer who has not developed anything so far :)
I like to "number"x2 (multiply by 2) shows up in front of "result" after clicking "Calculation" button.
also, how can I show the result on another page/screen?
here is a pic of the app
enter image description here
here is my code:
MainPage.xaml
<StackLayout>
<Label
Text="Give me a number"
Margin="0,50,0,0" Padding="13,0,0,0"/>
<Entry Placeholder="number"
x:Name="numb"
Keyboard="Numeric"
Margin="130,-30,40,0"
Opacity="1" Rotation="0"
TranslationX="16" />
<Button Text=" Calculate "
BackgroundColor="#F6DEDE"
FontSize="Large"
FontAttributes="Bold"
/>
<Label
Text=" Result "
FontSize="30"
Margin="0, 20, 0, 0"
Padding="10,0,0,0"/>
</StackLayout>
Here is MainPage.xaml.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Test
{
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
void CalculateClicked(object sender, EventArgs args)
{
float numb = float.Parse(this.numb.Text);
float B = 100 * numb * 2;
// show B in front of result or on another page
}
}
}
first, give a name to your Label
<Label x:Name="result"
Text=" Result "
FontSize="30"
Margin="0, 20, 0, 0"
Padding="10,0,0,0"/>
Now, you have to set the result in the label
void CalculateClicked(object sender, EventArgs args)
{
float numb = float.Parse(this.numb.Text);
float B = 100 * numb * 2;
result.Text = $": {B}";
}
As the two answers already points out, you need to give a name to the label in xaml and then you can use it in code behind to set the text.
void CalculateClicked(object sender, EventArgs args)
{
float numb = float.Parse(this.numb.Text);
float B = 100 * numb * 2;
// show B in front of result or on another page
resultLabel.Text = B.ToString();
}
Another thing you need to do is add a click event to the button and assign CalculateClicked to it. Then when you click the button, CalculateClicked method will be triggered:
<Button Text=" Calculate "
BackgroundColor="#F6DEDE"
FontSize="Large"
FontAttributes="Bold"
Clicked="CalculateClicked"
/>
first, give your Label a name
<Label x:Name="lblResult"
Text=" Result "
FontSize="30"
Margin="0, 20, 0, 0"
Padding="10,0,0,0"/>
then you can assign it a value from code
void CalculateClicked(object sender, EventArgs args)
{
float numb = float.Parse(this.numb.Text);
float B = 100 * numb * 2;
// show B in front of result or on another page
lblResult.Text += ": " + B.ToString();
}
Related
I have spent my recent hours on researching on how to make this possible
I have a bottom tabbed page with a home button. What I want to achieve is, when button is pressed for x seconds, a new page shall be opened. How should the custom renderer for the tabbed page look like?
I already have one custom renderer for the tabbed page that makes sure that the home page button is a floating action button. The custom renderer for the home page button:
[assembly: ExportRenderer(typeof(NavigationBar), typeof(CustomTabbedRenderer))]
namespace MysteryLocation.Droid
{
public class CustomTabbedRenderer : TabbedPageRenderer
{
Context context;
public CustomTabbedRenderer(Context context) : base(context)
{
this.context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
if (e.OldElement == null && e.NewElement != null)
{
for (int i = 0; i <= this.ViewGroup.ChildCount - 1; i++)
{
var childView = this.ViewGroup.GetChildAt(i);
if (childView is ViewGroup viewGroup)
{
((ViewGroup)childView).SetClipChildren(false);
for (int j = 0; j <= viewGroup.ChildCount - 1; j++)
{
var childRelativeLayoutView = viewGroup.GetChildAt(j);
if (childRelativeLayoutView is BottomNavigationView bottomView)
{
FloatingActionButton button = new FloatingActionButton(context);
BottomNavigationView.LayoutParams parameters = new BottomNavigationView.LayoutParams(150, 150);
parameters.Gravity = GravityFlags.CenterHorizontal;
Drawable d = Resources.GetDrawable(Resource.Drawable.image);
button.SetScaleType(Android.Widget.ImageView.ScaleType.Center);
button.SetImageDrawable(d);
button.LayoutParameters = parameters;
bottomView.AddView(button);
}
}
}
}
}
}
}
}
==========
EDIT
==========
In my customtabbedrenderer I've added button.LongClick += Button_LongClick and button.Click += Button_Click with the methods
private void Button_LongClick(object sender, EventArgs e)
{
//open a page through pushasync
}
private void Button_Click(object sender, EventArgs e)
{
//navigate to the page as usual, as it does when there's no
"button.Click" specified in the custom renderer
}
Any ideas on how the code should look like in the given methods?
=========
EDIT 2
=========
I have solved on long click, a new page is being opened through
button.LongClick += (object sender, LongClickEventArgs args) =>
{
Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(new Pass()));
};
The app works both on click and on long click now. The remaining problem is, how can I allow the same button to navigate to the page that it is supposed to when only doing a simple click? It navigates to that page when there's no "button.Click += Button_Click" and "button.LongClick += Button_Click1". But as soon as I add a longclick event, the button stops working on click.
==========================
SOLVED
==========================
Added Element.CurrentPage = Element.Children[2] in the method Button_Click method, simple as that.
Longpress may be problematic in XF. For one of my applications I used a double tap:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:CustomCtrls ="clr-namespace:D4503.CustomControls"
xmlns:Views="clr-namespace:D4503.Views"
x:Class="D4503.Pages.MainPage"
BackgroundColor="{StaticResource ScreenBackColor}"
ios:Page.UseSafeArea="true">
<ContentPage.Content>
<StackLayout>
<Image Grid.Row="1" Grid.Column="0" x:Name="btnRed" Style="{StaticResource ColorButtonImage}" Source="stoplight_red.png"
Aspect="AspectFit">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="Red_Button_Tapped"/>
<TapGestureRecognizer Tapped="Red_Button_Tapped_Double" NumberOfTapsRequired="2" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
</ContentPage.Content>
</ContentPage>
We are working on show/ hide password toggle functionality in Xamarin traditional approach. What is the best place to implement it? Is it in Xamarin.iOS &. Droid or in Xamarin.Core?
If it is in Xamarin.Core, can you let us know the process. Is it by value convertors?
Thanks in advance.
Recently, Microsoft MVP Charlin, wrote an article showing how to do this using Event Triggers in the Xamarin Forms code:
She was able to do it simply using a new ShowPasswordTriggerAction of type TriggerAction that implemented INotifyPropertyChanged.
Therein, she created a HidePassword bool property that Invoke a PropertyChanged event which changes the Source of the Icon image:
protected override void Invoke(ImageButton sender)
{
sender.Source = HidePassword ? ShowIcon : HideIcon;
HidePassword = !HidePassword;
}
Then place the Entry and ImageButton inside a layout (like a Frame or horizontally oriented LinearLayout) as shown:
<Entry Placeholder="Password"
IsPassword="{Binding Source={x:Reference ShowPasswordActualTrigger}, Path=HidePassword}"/>
<ImageButton VerticalOptions="Center"
HeightRequest="20"
HorizontalOptions="End"
Source="ic_eye_hide">
<ImageButton.Triggers>
<EventTrigger Event="Clicked">
<local:ShowPasswordTriggerAction ShowIcon="ic_eye"
HideIcon="ic_eye_hide"
x:Name="ShowPasswordActualTrigger"/>
</EventTrigger>
</ImageButton.Triggers>
</ImageButton>
We always use custom controls to show/hide password while entering the password using effects.
Android:
Create the control manually in ‘OnDrawableTouchListener’ method where, we are adding the ShowPass and HidePass icons to the entry control, changing them on the basis of user touch action and attaching it on effect invocation which will be fired when the effect is added to the control.
public class OnDrawableTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
{
public bool OnTouch(Android.Views.View v, MotionEvent e)
{
if (v is EditText && e.Action == MotionEventActions.Up)
{
EditText editText = (EditText)v;
if (e.RawX >= (editText.Right - editText.GetCompoundDrawables()[2].Bounds.Width()))
{
if (editText.TransformationMethod == null)
{
editText.TransformationMethod = PasswordTransformationMethod.Instance;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.ShowPass, 0);
}
else
{
editText.TransformationMethod = null;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.HidePass, 0);
}
return true;
}
}
return false;
}
}
Result:
IOS:
Create the control manually in 'ConfigureControl' method where we are adding the ShowPass and HidePassicons to the entry control, changing them on the basis of user touch action; and attaching it on effect invocation which will be fired when the effect will be added to the control.
private void ConfigureControl()
{
if (Control != null)
{
UITextField vUpdatedEntry = (UITextField)Control;
var buttonRect = UIButton.FromType(UIButtonType.Custom);
buttonRect.SetImage(new UIImage("ShowPass"), UIControlState.Normal);
buttonRect.TouchUpInside += (object sender, EventArgs e1) =>
{
if (vUpdatedEntry.SecureTextEntry)
{
vUpdatedEntry.SecureTextEntry = false;
buttonRect.SetImage(new UIImage("HidePass"), UIControlState.Normal);
}
else
{
vUpdatedEntry.SecureTextEntry = true;
buttonRect.SetImage(new UIImage("ShowPass"), UIControlState.Normal);
}
};
vUpdatedEntry.ShouldChangeCharacters += (textField, range, replacementString) =>
{
string text = vUpdatedEntry.Text;
var result = text.Substring(0, (int)range.Location) + replacementString + text.Substring((int)range.Location + (int)range.Length);
vUpdatedEntry.Text = result;
return false;
};
buttonRect.Frame = new CoreGraphics.CGRect(10.0f, 0.0f, 15.0f, 15.0f);
buttonRect.ContentMode = UIViewContentMode.Right;
UIView paddingViewRight = new UIView(new System.Drawing.RectangleF(5.0f, -5.0f, 30.0f, 18.0f));
paddingViewRight.Add(buttonRect);
paddingViewRight.ContentMode = UIViewContentMode.BottomRight;
vUpdatedEntry.LeftView = paddingViewRight;
vUpdatedEntry.LeftViewMode = UITextFieldViewMode.Always;
Control.Layer.CornerRadius = 4;
Control.Layer.BorderColor = new CoreGraphics.CGColor(255, 255, 255);
Control.Layer.MasksToBounds = true;
vUpdatedEntry.TextAlignment = UITextAlignment.Left;
}
}
Result:
For more details, please refer to the article below.
https://www.c-sharpcorner.com/article/xamarin-forms-tip-implement-show-hide-password-using-effects/
You could download the source file from GitHub for reference.
https://github.com/techierathore/ShowHidePassEx.git
You can use the PhantomLib library to do this. It has a control which allows you to have a show/hide icon for the password with examples. Just install the nuget. https://github.com/OSTUSA/PhantomLib
Your UI codes like this having a entry and image button
source to named accroding to your ui
<Frame CornerRadius="30" Background="white" Padding="0" HeightRequest="43" Margin="0,17,0,0">
<StackLayout Orientation="Horizontal">
<Entry x:Name="eLoginPassword"
Margin="15,-10,0,-15"
HorizontalOptions="FillAndExpand"
IsPassword="True"
Placeholder="Password"/>
<ImageButton
x:Name="ibToggleLoginPass"
Clicked="IbToggleLoginPass"
Source="eyeclosed"
Margin="0,0,13,0"
BackgroundColor="White"
HorizontalOptions="End"
/>
</StackLayout>
</Frame>
in C# code
// IbToggleLoginPass your defined method in xaml
//"eye" is drawable name for open eye and "eyeclosed" is drawable name for closed eye
private void IbToggleLoginPass(object sender, EventArgs e)
{
bool isPass = eLoginPassword.IsPassword;
ibToggleLoginPa`enter code here`ss.Source = isPass ? "eye" : "eyeclosed";
eLoginPassword.IsPassword = !isPass;
}
Trigger and a command
The trigger changes the icon, and the command changes the entry.
View xaml
<Grid>
<Entry Placeholder="Password" Text="{Binding Password, Mode=TwoWay}" IsPassword="{Binding IsPassword}" />
<ImageButton BackgroundColor="Transparent" WidthRequest="24" VerticalOptions="Center" TranslationY="-5" TranslationX="-10" HorizontalOptions="End"
Command="{Binding ToggleIsPassword}"
Source="eye" >
<ImageButton.Triggers>
<DataTrigger TargetType="ImageButton" Binding="{Binding IsPassword}" Value="True" >
<Setter Property="Source" Value="eye-slash" />
</DataTrigger>
</ImageButton.Triggers>
</ImageButton>
</Grid>
And in my ViewModel
private bool _IsPassword = true;
public bool IsPassword
{
get
{
return _IsPassword;
}
set
{
_IsPassword = value;
RaisePropertyChanged(() => IsPassword);
}
}
public ICommand ToggleIsPassword => new Command(() => IsPassword = !IsPassword);
I have wired up my ContentPage to an instance of a class (g), and this case works fine:
open the page
enter values in the Entry boxes
make a selection from a DisplayActionSheet
click Save
OnSave all the values from the UI are in g, but the value from the DisplayActionSheet is not in the UI where I expect it.
After the DisplayActionSheet thing runs, I want a value for AisleDepthText to display in the UI.
Here is the class that I instantiate into a variable, g
public class GroceryItemForSaving
{
public GroceryItemForSaving() { }
public event PropertyChangedEventHandler PropertyChanged;
private string _AisleDepth;
public string AisleDepth
{
get
{
return _AisleDepth;
}
set
{
_AisleDepth = value;
OnPropertyChanged();
}
}
private string _AisleDepthText;
public string AisleDepthText
{
get
{
return _AisleDepthText;
}
set
{
_AisleDepthText = value;
OnPropertyChanged();
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
I make g the BindingContext like this:
public NewGrocery()
{
InitializeComponent();
BindingContext = g;
}
Here is the relevant XAML.
<Label Text="GroceryName" Grid.Row="0" Grid.Column="1" ></Label>
<Entry Text="{Binding GroceryName}" Grid.Row="0" Grid.Column="2" ></Entry>
<Label Text="Aisle" Grid.Row="1" Grid.Column="1" ></Label>
<Entry Text="{Binding Aisle}" Grid.Row="1" Grid.Column="2"></Entry>
<Label Text="Aisle Depth" Grid.Row="2" Grid.Column="1" ></Label>
<Label Text="{Binding AisleDepthText, Mode=OneWay}" Grid.Row="2" Grid.Column="2" ></Label>
<Button Clicked="ShowAisleDepthChoices" Grid.Row="2" Grid.Column="3" Text="Aisle Depth" ></Button>
The button click handler ShowAisleDepthChoices, makes the ActionSheet display. In the code for that I set the values for AisleDepth and AisleDepthText like this:
public async void ShowAisleDepthChoices(object sender, EventArgs e)
{
var AisleDepth = 0;
var SelectedAisleDepth = await DisplayActionSheet("Aisle Depth", "Cancel", null, "Front", "Middle", "Back", "Back Wall");
switch (SelectedAisleDepth)
{
case "Front":
AisleDepth = 1;
break;
case "Middle":
AisleDepth = 2;
break;
case "Back":
AisleDepth = 3;
break;
case "Back Wall":
AisleDepth = 4;
break;
}
g.AisleDepthText = SelectedAisleDepth;
g.AisleDepth = AisleDepth.ToString();
}
Then after that no value appears in AisleDepthText Label, but when I click Save, the values are in g.AsileDepthText and g.AisleDept exactly where I expect them. NOTE: I can enter a GroceryName directly in the UI and it ends up in g.GroceryName on save.
What do I need to do to make the value for g.AisleDepthText appear in the UI after the DisplayActionSheet does its thing?
GroceryItemForSaving needs to implement INotifyPropertyChanged. You have to code to satisfy the implementation, but you're not declaring that the class uses the interface, so your binding isn't updating like it should.
public class GroceryItemForSaving : INotifyPropertyChanged
I had this code working before, but have somehow deleted it as I was trying to get something else fixed.
So I have a list which is bound as a View model, and the list has three lines on it.
I want to be able to click on the list, get the value of the third line on another page and use that value.
Here is the code for the selection of the list
private void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// If selected index is -1 (no selection) do nothing
if (List.SelectedIndex == -1)
return;
// Navigate to the new page
NavigationService.Navigate(new Uri("/Route.xaml?selectedItem=" + List.SelectedIndex, UriKind.Relative));
string urlWIthData = string.Format("/Route.xaml?name={0}", " ");
this.NavigationService.Navigate(new Uri(urlWIthData, UriKind.Relative));
// Reset selected index to -1 (no selection)
List.SelectedIndex = -1;
}
Then, on the route page I want to be able to get the value and use the value line three....
How do I do this?
EDIT:
so this one part of the list:
this.Items.Add(new ItemViewModel() { LineOne = "Images/1.png", LineTwo = "Whitehawk - County
Hospital - City Centre - Hove - Portslade - Mile Oak", LineThree = "1 Whitehawk - Mile Oak",
LineFour = "1 Mile Oak - Whitehawk", LineFive = "1149" });
I Display the list on one page :
<ListBox Margin="6,6,7,6" ItemsSource="{Binding Items}" Name="List" OpacityMask="#FFD38648" FontSize="26" SelectionChanged="List_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17" DataContext="{Binding}">
<Image Name="Images" Source="{Binding LineOne}">
</Image>
<TextBlock Text="{Binding LineTwo}" Style="{StaticResource PhoneTextSubtleStyle}" Name="textblock3"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You can cast the list's SelectedItem to type Item and get the value from there:
private void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// If selected index is -1 (no selection) do nothing
if (List.SelectedIndex == -1)
return;
// Here's the codes -----------------------
var item = Items.SelectedItem as Item;
if(item == null) //cast didn't work
return;
var lineThree = item.LIneThree;
// end of the codes -----------------------
// Navigate to the new page
NavigationService.Navigate(new Uri("/Route.xaml?selectedItem=" + List.SelectedIndex, UriKind.Relative));
string urlWIthData = string.Format("/Route.xaml?name={0}", " ");
this.NavigationService.Navigate(new Uri(urlWIthData, UriKind.Relative));
// Reset selected index to -1 (no selection)
List.SelectedIndex = -1;
}
In my app I have several pages. When I click on the Windows "Back" Button everything goes back as expected.
However I have 2 pages that are causing me grief. Page "A" is doing some binding in the XAML:
<ListBox x:Name="lbPrograms" ItemsSource="{Binding Items}" SelectionChanged="lbPrograms_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="DataTemplateStackPanel" Orientation="Horizontal">
<Image x:Name="ItemImage" Source="/images/ArrowImg.png" Height="43" Width="43" VerticalAlignment="Top" Margin="10,0,20,0"/>
<StackPanel>
<TextBlock x:Name="ItemText" Text="{Binding programName}" Margin="-2,-13,0,0" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock x:Name="DetailsText" Text="{Binding createDate}" Margin="0,-6,0,3" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
<Image x:Name="ItemFavs" Source="/images/favs.png" Height="43" Width="43" VerticalAlignment="Top" Margin="10,0,20,0"/>
<Image x:Name="ItemDelete" Source="/images/delete.png" Height="43" Width="43" VerticalAlignment="Top" Margin="10,0,20,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The code behind for Page A is fairly simple:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// Set the data context of the listbox control to the sample data
if (DataContext == null)
DataContext = App.ViewModel;
App.ViewModel.Refresh();
lbPrograms.ItemsSource = App.ViewModel.Items;
}
private void lbPrograms_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
NavigationService.Navigate(new Uri("/DisplayProgram.xaml?selectedItem=" + lbPrograms.SelectedIndex, UriKind.Relative));
}
private void BackBtn_Click(object sender, EventArgs e)
{
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
Page B has no binding in the XAML as I am taking the data from the ModelView a drawing it out dynamically on the screen. Like so:
private int index;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string selectedIndex = "";
if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex))
{
//prevents error
if (int.Parse(selectedIndex) == -1)
{
return;
}
if ((DataContext == null))
{
index = int.Parse(selectedIndex);
App.ViewModel.Refresh();
DataContext = App.ViewModel.Items[index].nValDictionary;
int i = 0;
foreach (KeyValuePair<string, string> kvp in (((System.Collections.Generic.Dictionary<string, string>)(DataContext))))
{
StackPanel sp = new StackPanel();
sp.Name = "sp" + i;
sp.Background = new SolidColorBrush(Colors.Black);
sp.Width = 460;
WrapPanel wp = new WrapPanel();
wp.Name = "test" + i;
wp.Width = 300;
wp.Height = 200;
TextBlock txt = new TextBlock();
txt.Text = kvp.Key.ToString();
txt.Foreground = new SolidColorBrush(Colors.White);
sp.Children.Add(txt);
int chkBoxesVal = 0;
if (kvp.Value == "")
{
chkBoxesVal = 0;
}else{
chkBoxesVal = Convert.ToInt32(kvp.Value.ToString());
}
int iCount = 0;
for (iCount = 0; iCount <= chkBoxesVal - 1; iCount++)
{
CheckBox chk = new CheckBox();
chk.Name = i.ToString();
chk.Width = 56;
chk.Height = 70;
chk.Content = "";
//chk.Background = new SolidColorBrush(Colors.Black);
//chk.BorderBrush = new SolidColorBrush(Colors.White);
chk.Style = (Style)Application.Current.Resources["checkBoxNG"];
wp.Children.Add(chk);
}
sp.Children.Add(wp);
lbItems.Items.Add(sp);
i += 1;
}
}
}
}
}
So when I'm going forward everything works fine, but when I hit the Windows "Back" button on Page B I get an error. I stepped through my code and when I hit the "Back" button it does go back to Page A, but then it is also going to Page B, which then throws the error and stops. So can anyone tell me why this behavior is happening? I would expect that it would go back to Page A and just stop there. Not to go back to Page B. is there something in my code that is causing it to reload Page B? Any resources that you can provide that might explain this behavior is also welcome!
Thanks!
It looks like SelectionChanged on Page A is firing as a result of the ItemsSource initialisation you're doing in OnNavigatedTo.
You could verify the SelectedIndex is -1 before taking any action in the SelectionChanged event.
Alternatively you could remove any existing event handler on SelectionChanged while doing this initialisation and restore that event handler on completion.
My assumption is that lbPrograms_SelectionChanged event occurs when you press back button and page A is loaded again.
Change your navigation design. For your DataTemplateStackPanel you could use ManipulationStarted event
and inside add
NavigationService.Navigate(new Uri("/DisplayProgram.xaml?selectedItem=" + lbPrograms.SelectedIndex, UriKind.Relative));