Closing a page in WPF - c#

I am new to C#, I just created a new page and want to close it in the XAML side I have:
<Grid>
<Button Content="Back" Click="Button_Click_Exit"
HorizontalAlignment="Left" Margin="220,263,0,0"
VerticalAlignment="Top" Width="75"/>
</Grid>
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace UI
{
/// <summary>
/// Interaction logic for calibrationPage.xaml
/// </summary>
public partial class calibrationPage : Page
{
public calibrationPage()
{
InitializeComponent();
}
private void Button_Click_Exit(object sender,
RoutedEventArgs e)
{
Close();
}
}
}
I think this supposed to be really simple, somehow I get this error, when I try to build it:
error CS1061: 'UI.calibrationPage' does not contain a definition for 'Close'
and no extension method 'Close' accepting a first argument
of type 'UI.calibrationPage' could be found
Edit 1: I understand that close() does not exit, then rephrasing my question, how can I simply close the page using a button click?
Edit 2: For the benefit of others: I ended up using PageNavigator.NavigateTo function to navigate back and forth between pages, I do not think that there is a concept of closing one page in WPF. Thanks for everyone's participation.

You're not telling an object to close.
If you're just wanting a button to act on the event, I'd recommend click event or OnClick. If you are in VS you can just double click the button in the designer, it will auto populate everything for you.
If you want a form to close you can use similar methods from your WPF window.
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
On the other hand, if you wanted to create your own method (like in this case) you can do so like:
private void closeMethod()
{
// your code here
}
Then you call it with:
closeMethod();
Depending on your method you can tell it to do what you want on the page. Such as close the page or window.
You can also pass references in your methods
Refer to: Microsoft for methods.
Not sure if it fits here, but you may want to use Application.Exit(); in some cases, if so refer to: MSDN to find the difference.

You would think closing a page would be a trivial task, but there's no page.Close property so what is one to do? I don't think pages were designed to be opened and closed like Windows, but here's a solution that should solve the problem for most.
To start, create a new WPF application and add a page to it called Page1.
In MainWindow.xaml, create a grid with a button and frame to display your page. (The frame is a key element because you can close the page by setting the frame.content = Nothing)
<Window x:Class="MainWindow"
...
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top">
<Button Content="Page1" Click="Page1_Click" Height="40"/>
</StackPanel>
<Frame x:Name="mainframe" Margin="0,50,0,0" NavigationUIVisibility="Hidden"/>
</Grid>
</Window>
In MainWindow.xaml.vb, add this code to display the page within the frame...
Class MainWindow
Private Sub Page1_Click(sender As Object, e As RoutedEventArgs)
Dim page1 As New Page1(mainframe)
mainframe.Content = page1
End Sub
End Class
In Page1.xaml, create a grid with a button to close the page...
<Page x:Class="Page1">
...
<Grid>
<Button Click="Page1Button_Click" Content="Close Page 1" Height="140" Width="140"/>
</Grid>
</Page>
And in your Page1.xaml.vb, close the page like this...
Class Page1
Private mainwin_frame As Frame
Public Sub New(localframe As Frame)
InitializeComponent()
mainwin_frame = localframe
End Sub
Private Sub Page1Button_Click(sender As Object, e As RoutedEventArgs)
mainwin_frame.Content = Nothing
End Sub
End Class
The key to all of this working is passing the mainframe object to the Page1 constructor so the page can access it. I'm sure there are other ways to do this but this is a common sense approach imo.

Related

Click button through only part of a transparent image in wpf program

I am trying to implement the ability to click through only part of a transparent background. The background image is a solid gray and has 3 circles, a rectangle, and an oval shape. The image is transparent. Button 1 appears inside of the rectangle and button 2 appears inside of the oval. When the program runs both buttons are visible but currently not clickable because the image is in a grid and added after the buttons. I would like to make only the rectangle click through so button 1 can be clicked, but still keep the image ahead of button 2 so it is not clickable.
I've searched around quite a bit for a solution but have not found what I'm looking for. This example is a dumbed down version of what I'm currently working on - but the functionality is essentially the same. Any help would be appreciated.
Xaml:
<Window x:Class="TransparentClickThrough.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="ButtonOne" Click="ButtonOne_Click" Content="Button1" Width="50" Height="25" ></Button>
<Button x:Name="ButtonTwo" Content="Button2" Width="50" Height="25" Margin="379,100,59,148" Click="ButtonTwo_Click"></Button>
<Image Source="/TransparentClickThrough;component/background.png" />
</Grid>
</Window>
Code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TransparentClickThrough
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonOne_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("You clicked button 1!");
}
private void ButtonTwo_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("You clicked button 2!");
}
}
}
background - 3 circles, rectangle, and oval are all set to transparent
This is what the program looks like when running.
I was able to just add a Rectangle with transparent fill to the grid. Then I added an event "MouseDown" Interaction trigger to toggle the Visibility through a DataTrigger which in turn changed the background color.
Similar to this link link

Textblock/Textbox in XAML and C#

I am a complete "weekend warrior" to programming so go gentle on me, please...
I want to achieve a simple task, which I had no problem with in plain C# (TextBox.Text = "Something";)
I have a textbox and a textblock in XAML, and I want to populate them from C#, simple as that - run the web app and pull the predefined strings from the C# code. I have been searching for 2 days now and can't find a straight answer. I don't want any triggers (buttons), just filling e.g. textbox on load with a C# string. A simple code example on both XAML and C# side would be greatly appreciated!
Cheers,
Sasa
Not sure if I'm understanding your question...
<!--xaml-->
<TextBox x:Name="txtMyTextBox"/>
// C#
// Window constructor
public MyWindow()
{
InitializeComponent();
txtMyTextBox.Text = "Something";
}
One simple way to achieve what you try to achieve (if I understood correctly), is to add the UI elements to your window and set a Name for each of them. This way, you can access them in your code-behind as seen below.
<Window x:Class="WpfApplication1.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" Loaded="Window_Loaded">
<Grid>
<TextBox Name="TextBox1" HorizontalAlignment="Left" Height="23" Margin="37,37,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
<TextBlock Name="TextBlock1" HorizontalAlignment="Left" Margin="48,100,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="103" Width="239"/>
</Grid>
</Window>
While there are certainly more "refined" ways to achieve the same, once you named your UI elements in xaml, you can access them just as other object instances in your code-behind.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
TextBox1.Text = "Hello TextBox1!";
TextBlock1.Text = "Hello TextBlock1!";
}
}
}

Data binding TextBox to string in code behind fails

I'm attempting to bind a string property to a TextBox's Text field in XAML. I am doing this in a UserControl. I've searched StackOverflow and the internet in general and found various related topics, some examples:
Binding objects defined in code-behind
WPF: simple TextBox data binding
I've followed the code in these examples as best as I can but the Input property does not appear to be binding to the TextBox. I've tried various different methods of setting up the DataContext, including from the code behind and it's still not working.
What is it that I'm missing, is this an issue because it's a UserControl?
The code in the SearchInputTextBox_TextChanged event is called but always outputs an empty string. If I put a Debug.WriteLine call in the Input set section nothing happens.
The XAML file:
<UserControl x:Class="DatabaseViewerApp.View.SearchBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="70" d:DesignWidth="240"
x:Name="Control">
<Border Padding="5" Background="#303030">
<StackPanel>
<TextBlock Text="Search" Margin="0,0,0,0" FontSize="20px" Foreground="White"></TextBlock>
<TextBox Name="SearchInputTextBox" Text="{Binding ElementName=Control, Path=Input}" Margin="0,5" FontSize="15px" TextChanged="SearchInputTextBox_TextChanged"></TextBox>
</StackPanel>
</Border>
</UserControl>
The C# file:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DatabaseViewerApp.View
{
/// <summary>
/// Interaction logic for SearchBox.xaml
/// </summary>
public partial class SearchBox : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string input;
public string Input
{
get { return input; }
set
{
if (value != input)
{
input = value;
NotifyPropertyChanged("Input");
}
}
}
public void NotifyPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public SearchBox()
{
InitializeComponent();
}
private void SearchInputTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
Debug.WriteLine(Input);
}
}
}
I think your problem is not that it isn't working... The issue is that you may not be testing it properly. Your code works for me in a new WPF solution. What you may be missing is that the Text binding gets updated when you leave the focus. In contrast, the TextChanged event gets fired as soon as the text is input into the text box.
So, whats happening is that when the TextChanged event is fired, the binding hasn't yet been updated. If you try putting a breakpoint in your property setter, then change some text in the text box, and move focus out of that control, you should see it get hit.
As an aside, there isn't much sense in binding your Text to a property in the code behind because the UI element can be accessed directly from there.
Try this:
<TextBox Name="SearchInputTextBox"
Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=UserControl},Path=Input}"
Margin="0,5" FontSize="15px" TextChanged="SearchInputTextBox_TextChanged">
</TextBox>

Starting a custom window in wpf from code behind does not draw it's content

In my tests, I've created a simple class like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
namespace Test
{
public class MyCustomWindow: Window
{
}
}
This class is compiled into a dll.
In another project, I tried to use this custom window, like this:
<Custom:MyCustomWindow x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Custom="clr-namespace:Test;assembly=Test"
Title="MainWindow" Height="600" Width="1210" WindowState="Maximized" >
<Grid Background="Blue">
<Button Content="Button" HorizontalAlignment="Left" Margin="457,212,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
This thing compiles with no errors, and works great when the custom window is opened by the "StartupUri" in the App.xaml file (that defines the first window loaded).
However, if I set other window to load in the StartupUri, and:
MainWindow m = new MainWindow();
m.Activate();
m.Show();
this.Close();
The CustomWindow will open, but without any content, without button and without the blue grid - and even without the title.
Any workaround? And what I need to do to open a Window with the same behavior of the StartupUri?
Edit:
I've noticed that the MainWindow (or any window derived from MyCustomWindow) simply cannot have the method InitializeComponent() in the constructor, because it does not exist in the context. Strangely, when using StartupUri, the contents are loaded normally without this.
Edit 2:
I think that the problem is occurring because I can't put the InitializeComponent() method in the MyCustomWindow. This explains why the MainWindow can be loaded normally into the StartupUri: it's loading directly from the xaml file, so it's parsing the content without the need of the InitializeComponent.
I starting to think about implement the IComponentConnector interface, but I have no idea how to do this.
Edit 3:
The code-behind of the file MainWindow.xaml.cs is:
using Test;
namespace TestingCustomWindow
{
public partial class MainWindow : MyCustomWindow
{
public MainWindow()
{
// Cannot use InitializeComponent here
}
}
}
pls add the new window using Visual Studio and
Replace :Window with :MyCustomWindow. You will get initializecomponent. You will hav to update window tag with your CustumWindow tag in xaml also
Adding it as answer so other can use it.
Thanks
I think the constructor has to look like this
public class MyCustomWindow: Window
{
InitializeComponent();
}

Routed Events problem - hitting the root UI element before the child element

My routed events are hitting the root UI element before the child element. Is this expected? How can I have the routed events hit the child element first?
Objective: If text is typed anywhere other than "custom textbox", put text in "default textbox"
Result: Window_PreviewTextInput is being hit before custom_PreviewTextInput, even if my cursor focus is on "Custom Textbox"
What should I do differently?
XAML
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" SizeToContent="WidthAndHeight"
PreviewTextInput="Window_PreviewTextInput"
>
<Grid Margin="100,100,100,100">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="default" Width="100"/>
<TextBox x:Name="defaultTB" Width="300" Height="50"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="custom" Width="100"/>
<TextBox x:Name="custom" PreviewTextInput="custom_PreviewTextInput" Width="300" Height="50"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
Code Behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
//goal: if text is typed anywhere except custom textbox, put text in default textbox
private void Window_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
Keyboard.Focus(defaultTB);
}
//goal: if text is typed in custom TB, put text there, and end the event routing
private void custom_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = true;
}
}
}
Routed Event could be a bubbling or tunneling. You've a tunneling event behaviour.
From MSDN, UIElement.PreviewTextInput Event:
Routing strategy - Tunneling
The corresponding bubbling event is TextInput.
Routed Events Overview - Routing Strategies:
Bubbling: Event handlers on the event source are invoked. The routed
event then routes to successive parent elements until reaching the
element tree root. Most routed events use the bubbling routing
strategy. Bubbling routed events are generally used to report input or
state changes from distinct controls or other UI elements
Direct: Only the source element itself is given the opportunity to
invoke handlers in response. This is analogous to the "routing" that
Windows Forms uses for events. However, unlike a standard CLR event,
direct routed events support class handling (class handling is
explained in an upcoming section) and can be used by EventSetter and
EventTrigger.
Tunneling: Initially, event handlers at the element tree root are
invoked. The routed event then travels a route through successive
child elements along the route, towards the node element that is the
routed event source (the element that raised the routed event).
Tunneling routed events are often used or handled as part of the
compositing for a control, such that events from composite parts can
be deliberately suppressed or replaced by events that are specific to
the complete control. Input events provided in WPF often come
implemented as a tunneling/bubbling pair. Tunneling events are also
sometimes referred to as Preview events, because of a naming
convention that is used for the pairs.

Categories