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

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.

Related

Show a sequence of images in WPF then close form

I have a window that shows an open lock.
When the user clicks a button the lock must change to closed, wait a second and then close the windows.
How can I do that using WPF?
Here is my initial xaml:
<Button Grid.Row="2" BorderThickness="0" Background="Transparent" Margin="32"
IsTabStop="False" Click="BtnUnlockClick">
<Button.Content>
<Grid>
<Image Grid.Row="1" Source="/Common.Wpf;component/images/unlocked.png" Visibility="Visible" Name="imgUnlocked"/>
<Image Grid.Row="1" Source="/Common.Wpf;component/images/locked.png" Visibility="Collapsed" Name="imgLocked"/>
</Grid>
</Button.Content>
</Button>
and C#:
private void BtnUnlockClick(object sender, RoutedEventArgs e)
{
//do stuff here
}
Put only one Image element into the Button's Content.
<Button Click="BtnUnlockClick" ...>
<Image Source="/Common.Wpf;component/images/unlocked.png"/>
</Button>
In the Click event handler change its Source, wait a second, then close the Window. The handler method must be declared async.
private async void BtnUnlockClick(object sender, RoutedEventArgs e)
{
var image = (Image)((Button)sender).Content;
image.Source = new BitmapImage(
new Uri("pack://application:,,,/Common.Wpf;component/images/locked.png"));
await Task.Delay(1000);
Close();
}

UWP Navigation Pane go back button not working

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..!

Wpf PasswordBox must show characters when I click CheckBox

xaml
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel VerticalAlignment="Center" Width="300">
<PasswordBox x:Name="PasswordBox1" Height="30" PasswordChar="*" Password="12345"/>
<CheckBox x:Name="CheckBox1" Content="Show Password"/>
</StackPanel>
</Window>
vb.net
Class MainWindow
Private Sub CheckBox1_Checked(sender As Object, e As RoutedEventArgs) Handles CheckBox1.Checked
PasswordBox1.PasswordChar = CChar("")
End Sub
Private Sub CheckBox1_Unchecked(sender As Object, e As RoutedEventArgs) Handles CheckBox1.Unchecked
PasswordBox1.PasswordChar = CChar("*")
End Sub
End Class
Run the above codes and click CheckBox1 in order to understand what is happening.
How can PasswordBox show characters which are 12345 when I click CheckBox?
So, following line need to be repaired.
PasswordBox1.PasswordChar = CChar(" ")
This will work for what you are looking for although it will expose your passwords in memory. We have a textbox and a password box in the same place on our UI and when the user checks the Show Password checkbox we collapse the passwordbox and show the hidden textbox, at the same time updating the text. You will need to check you are using the password from the visible ui control when you send the password.
Xaml code:
<StackPanel Orientation="Horizontal">
<Grid Width="300" Height="40">
<PasswordBox Name="passwordBox" PasswordChar="*" />
<TextBox Name="passwordTxtBox" Visibility="Collapsed" />
</Grid>
<CheckBox Margin="10" Name="showPassword" Unchecked="ShowPassword_Unchecked" Checked="ShowPassword_Checked" />
</StackPanel>
Code behind:
private void ShowPassword_Checked(object sender, RoutedEventArgs e)
{
passwordTxtBox.Text = passwordBox.Password;
passwordBox.Visibility = Visibility.Collapsed;
passwordTxtBox.Visibility = Visibility.Visible;
}
private void ShowPassword_Unchecked(object sender, RoutedEventArgs e)
{
passwordBox.Password = passwordTxtBox.Text;
passwordTxtBox.Visibility = Visibility.Collapsed;
passwordBox.Visibility = Visibility.Visible;
}
I recommend Using MahApps.Metro ... after installing it from nuget.org ... you must import it in the head of your xaml like this xmlns:controls="http://metro.mahapps.com/winf/xaml/controls"
and then ... just use it's style for your PasswordBox control
<PasswordBox Style="{StaticResource MetroButtonRevealedPasswordBox}" />
you can even change the content for the show icon using the controls:PasswordBoxHelper.RevealButtonContent attached property

How to Overlay a Popup in a Specific Pivot Item

This is an interesting question, but I would like to overlay a popup only on a single PivotItem within my PivotPage, and only after a certain number of 'events' occurs (the events being a click event, say 50 times clicked). I have in my PivotItem a ListBox, but I am wondering how after my condition is met that I can overlay a popup over it?
XAML
<phone:PivotItem Header="{Binding Path=LocalizedResources.EditPage_Header_Effects, Source={StaticResource LocalizedStrings}}">
<ListBox Name="ListBoxEffects" SelectionMode="Single" ItemsSource="{Binding}" Margin="{Binding}"
toolkit:TiltEffect.IsTiltEnabled="True" SelectionChanged="ListBox_SelectionChanged" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel ItemWidth="146" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="12,0,0,24" >
<Image Source="{Binding Thumbnail}" Width="134" Height="134" />
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeNormal}" VerticalAlignment="Center" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</phone:PivotItem>
Code Behind
private void BuildLocalizedApplicationBar()
{
// Set the page's ApplicationBar to a new instance of ApplicationBar.
ApplicationBar = new ApplicationBar();
ApplicationBarIconButton saveButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/save.png", UriKind.Relative));
saveButton.Text = AppResources.EditPage_ApplicationBar_Save;
saveButton.Click += saveButton_Click;
ApplicationBar.Buttons.Add(saveButton);
}
void saveButton_Click(object sender, EventArgs e)
{
Settings.SavedCount.Value += 1;
if(Settings.SavedCount.Value > 50)
//Display Popup
ApplySelectedEffectAndSaveAsync();
}
Also, I would need to somehow retrieve the resulting value of the popup (From an OK or Cancel button), and depending on that result either call the ApplySelectedEffectAndSaveAsync() method or return to the previous PivotItem (or previous page). The PivotItem with the overlay is actually index 1 and there is another PivotItem before it with index of 0.
<phone:PivotItem ...>
<Grid>
<ListBox .../>
<Popup Name="MyPopup" IsOpen="false"/>
</Grid>
</phone:PivotItem>
And you manage MyPopup from code behind (you count the clicks or events and set MyPopup.IsOpen = true)
It seems like you are looking for MessageBox.Show. This method shows a popup with your own caption, text and either an OK or OK and cancel buttons. The method returns a MessageBoxResult value which is either MessageBoxResult.OK or MessageBoxResult.Cancel.
This is how it should be implemented in your code:
private void BuildLocalizedApplicationBar()
{
// Set the page's ApplicationBar to a new instance of ApplicationBar.
ApplicationBar = new ApplicationBar();
ApplicationBarIconButton saveButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/save.png", UriKind.Relative));
saveButton.Text = AppResources.EditPage_ApplicationBar_Save;
saveButton.Click += saveButton_Click;
ApplicationBar.Buttons.Add(saveButton);
}
void saveButton_Click(object sender, EventArgs e)
{
Settings.SavedCount.Value += 1;
if(Settings.SavedCount.Value > 50)
{
if(MessageBox.Show("Message", "Title", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
// Action for "OK"
else
// Action for "Cancel"
}
}

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>

Categories