Cast Page for accessing textbox/object of other page - c#

Previously, I had only one xaml-file, which was the only Windows, namely the mainWindow.
To access any button / textbox / object from another class (explicetly a non-static class) I can just cast the Window like this
mainWindow mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(w => w is mainWindow) as mainWindow;
Now my question is, how does this work for several pages, since now I have a Frame, where I load several pages to.
Actually it does NOT work like this:
myPage page = Application.Current.Windows.Cast<Page>().FirstOrDefault(p => p is myPage) as myPage;
There is a runtime-error, which says:
System.InvalidCastException: Object of type "namespace.mainWindows" cannot be converted to object of type "System.Windows.Controls.Page"

make MainWindow return a Page, which is displayed:
public class mainWindow
{
public Page GetCurrentPage()
{
// return known Page;
};
}
and then:
mainWindow mainWin = Application.Current.Windows.OfType<mainWindow>().FirstOrDefault();
Page p = mainWin?.GetCurrentPage();

This one worked out for me:
MainWindow
namespace myName
{
public partial class main : Window
{
public main()
{
// ...
}
}
}
Textbox and Frame, where the page is load into, in the xaml-file of the mainWindow
Note, the FieldModifier is set to public!
<TextBox x:Name="textbox_main" Text="testString main" x:FieldModifier="public"/>
<Frame x:Name="myFrame" x:FieldModifier="public"/>
Page
namespace myName
{
public partial class myPage : Page
{
public myPage()
{
// ...
}
}
}
Textbox in the xaml-file of the Page
Note, the FieldModifier is set to public!
<TextBox x:Name="textbox_page" Text="testString page" x:FieldModifier="public"/>
After that, one is able to access the two textboxes (one directly in the window, one in a page of the window) in any other class via the following commands:
// get instance of the main-Window
main mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(w => w is main) as main;
// Access objects of the main-Window
Console.WriteLine(mainWin.textbox_main.Text);
// get instance of the current page of the certain frame
myPage page = (myPage)Application.Current.Windows.OfType<main>().FirstOrDefault().myFrame.Content;
// Access objects of the page
Console.WriteLine(page.textbox_page.Text);

Related

How can I pass a string from windows.xaml to a usercontrol.xaml

i have a Mainwindow.Xaml(wpf form) and 2x UserControl(EventPage.xaml and dashboard.xaml) inside this MainWindow.xaml i have a textbox and a button and i using this code to switch between my forms(EventPage.Xaml and Dashboard.Xaml) inside this Grid:
<Grid x:Name="myContainer">
<Local:EventPage x:Name="eventpage" Visibility="Collapsed"></Local:EventPage>
<Local:Dashboard x:Name="dashboard" Visibility="Collapsed"></Local:Dashboard>
</Grid>
now i wanna pass my textbox.text to my Dashboard.Xaml with this code:
public partial class MainWindow : Window
{
public string Searchtext;
public MainWindow()
{
InitializeComponent();
}
private void SearchBtn_Click(object sender, RoutedEventArgs e)
{
Searchtext = txtSearch.Text;
Dashboard dashPage = new Dashboard(Searchtext);
}
and in my usercontrol.xaml(Dashboard.Xaml) i have this code to recive my Searchtext :
public partial class Dashboard : UserControl
{
string searchtxt;
public Dashboard(string searchtext)
{
InitializeComponent();
searchtxt = searchtext;
}
but i getting this error from Mainwindows.xaml in this line:
<Local:Dashboard x:Name="dashboard" Visibility="Collapsed"></Local:Dashboard>
first Error: Type 'Dashboard' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter.
second Error: the type 'Dashboard' cannot have a Name attribute.Value types without a default constructor can be used as items within a ResourceDictionary.
Explanation
Ok. There's a few things to break down here.
1.
Your MainWindow.xaml indicates to the program which UI classes to intialise in order to create the UI and for every element that is in the .xaml, the class that it is from will be initialised
This means that
<Local:Dashboard x:Name="dashboard" Visibility="Collapsed"></Local:Dashboard>
Will run this code at the background at runtime:
Dashboard dashboard = new Dashboard();
dashboard.Name = "dashboard";
dashboard.Visibility = Visibility.Collapsed;
That means that you DO NOT need:
Dashboard dashPage = new Dashboard(Searchtext);
in your MainWindow.xaml.cs because the Dashboard has already been created when the UI was loaded.
2.
The second problem is that you have put a parameter inside the only constructor of the Dashboard class
Dashboard(string searchtext)
This means that when program tries to create the UI from the MainWindow.xaml it is not able to because it tries to call
new Dashboard();
but that is not possible because you have a parameter.
Basically if you have parameters in the constructor of Dashboard such as Dashboard(string searchtext)
then the program won't be able to load a Local:Dashboard element in the UI because the UI CAN NOT set the string searchtext.
This is why you get the error "does not define a public parameterless constructor..."
For the second error, ensure that in your ui you only set x:Name
Solution
Use the dashboard variable that the compiler creates from the UI to set the variable in the Dashboard.xaml.cs class.
MainWindow.xaml
<Grid x:Name="myContainer">
<Local:EventPage x:Name="eventpage" Visibility="Collapsed"></Local:EventPage>
<Local:Dashboard x:Name="dashboard" Visibility="Collapsed"></Local:Dashboard>
</Grid>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
}
private void SearchBtn_Click(object sender, RoutedEventArgs e)
{
dashboard.searchtxt = txtSearch.Text;
}
You also need to make the string in Dashboard.xaml.cs public and remove the parameter from the constructor:
public partial class Dashboard : UserControl
{
public string searchtxt;
public Dashboard()
{
InitializeComponent();
}

Passing data (get/set) between pages

I'm looking to do something very simple (or what I perceive as simple).
Basically, I have two pages set up in my XAML/C# UWP app, the first has a series of textboxes and dropdown menus to select options (Name, State, etc).
On the bottom there is a button to go to the next page.
On the next page, I would like to be able to display the user entered data.
I'm trying to figure out the best way to do this, but after hours of searching, I can't seem to figure out how to pass multiple values between pages. I think I want to create a Class file that stores all of this info, but I'm not exactly sure how to set the values in the C# code from the first page and get the info on the second page.
UPDATE:
So using the answer below I've gotten here:
On the MainPage
public sealed partial class MainPage : Page
{
public static MainPage Current;
public static string PageOneSelection
{
get; set;
}
public void changeToNextPage()
{
PageToLoad.Navigate(typeof(TwoPlayerGame));
}
public MainPage()
{
this.InitializeComponent();
Current = this;
PageToLoad.Navigate(typeof(Selection));
}
}
}
And on the Selection Page:
public sealed partial class Selection : Page
{
new string Name;
public Selection()
{
this.InitializeComponent();
}
private void PlayButton(object sender, TappedRoutedEventArgs e)
{
MainPage.Current.PageOneSelection = PlayerOneName.Text;
MainPage.Current.changeToNextPage();
}
}
}
You should have a MainPage which holds all of your pages in Frames.
<Page x:Name="Main">
<Frame x:Name="PageToLoad">
</Page>
On the MainPage you have a global which holds "this" and globals to store your selection values from the various pages.
public static MainPage Current;
public static string PageOneSelection;
And functions to get/store your selections:
public string getPageOneSelection()
{
return PageOneSelection;
}
public void setPageOneSelection(string whatToSetItTo)
{
PageOneSelection=whatToSetItTo;
}
On Initialization
// This is a static public property that allows downstream pages to get a handle to the MainPage instance
// in order to call methods that are in this class.
Current = this;
On Initialize of the MainPage you should load the first page:
PageToLoad.Navigate(/*Your First Page*/);
Now whenever they make a selection you can call back and forth to the MainPage to change that selection value
//On Page 1
MainPage.Current.setPageOneSelection(theSelectedItem);
//On Page 2
itemFromPage1=MainPage.Current.getPageOneSelection();
UPDATE: Your code looks good. So you say you have a textbox you want the information for. You can do this:
MainPage.Current.setPageOneSelection(textbox.Text);
I'd put this before you navigate to the next frame.
If you have a second selection (ie your dropdown), make another global on your MainPage and do the same thing.
Also if you have can send more than one string at a time, add parameters to your set function:
public void setAllPageOneSelections(string param1, string param2 /.../)
{
PageOneSelection=param1;
PageOneSelection2=param2;
}
In your Main you should probably have a page switcher function. I use:
public void changeToNextPage()
{
PageToLoad.Navigate(/*Page 2 or next page or something */);
}
and then for your play button you can do
MainPage.Current.changeToNextPage();
use this :-
define this variable:-
publicstatic mytextboxinfo {get;set;}
and in your function :-
submitbutton_Click(){
mytextboxinfo = mytextbox.text;
}
and then in the next page :-
Page_loaded() {
mytextbox2.Text = myPage.mytextboxinfo;
}
where "myPage" is the name of the page

WPF mainwindow content load from a page

I have one MainWindow and one page
I load the page content into the mainwindow by that code
NewPage abt = new NewPage();
this.Content = abt;
but how can I unload the page (reload the mainwindow control and close the page)
if I use the same code to load mainwindow content I get a runtime error
The way I have done this is to have a Frame in the XAML like so:
<Frame Grid.RowSpan="4" Grid.ColumnSpan="3" x:Name="_NavigationFrame" NavigationUIVisibility="Hidden"/>
And then I can set a page and unload a page with this:
_NavigationFrame.Navigate(customPage);
//code to hide main page controls
_NavigationFrame.Navigate(null);
//code to make main page controls visible
I don't think loading page into MainWindow content is a good solution, but if You need it You could probably get current state and save it to some property(or some other thing like xml file) before changing. Like Below:
public partial class MainWindow()
{
FrameworkElement previousContent; // I believe Content property is of FrameworkElement type
public MainWindow()
{
...
}
...
public void ChangeContent()
{
previousContent = this.Content; // save state
NewPage abt = new NewPage();
this.Content = abt; // set new state
}
//And later You can restore this state by:
public void RestorPreviousContent()
{
this.Content = previousContent;
}

How to pass window and string parameter from code behind into User Control

I have a bit off header that I need global to a few files so I have made a user control (I can't use the main window as this isn't global to all files) however there's two parameters that my user control needs, ScreenName and MainWindow to navigate on the home button click. Here is what I have tried so far:
public Header(MainWindow mainWindow, string screenName)
{
InitializeComponent();
DataContext = this;
ScreenName = screenName;
MainWindow = mainWindow;
ScreenNameTextBlock.Text = ScreenName;
}
public string ScreenName { get; set; }
public MainWindow MainWindow { get; set; }
private void Hyperlink_OnClick(object sender, RoutedEventArgs e)
{
//need to navigate home here
MainWindow.LoadScreenByCode("Menu");
}
You can probably assume the corresponding XAML as it's just a hyperlink and a textblock, but if you need it let me know.
I can include the user control like so:
<controls:Header x:Name="Header"></controls:Header>
But I can't figure out how to assign the parameters. If I try in the codebehind I can access the values like this:
Header.MainWindow = Shell;
Header.ScreenName = "Name";
But this causes the values to be null. Sorry if this is an easy issue, I am new to UserControls.
To access the main window of your application you should get the running instance of it as the following:
MainWindow myRunnningMainWindow = (Application.Current.MainWindow as MainWindow);
if(myRunningWindow!=null)
{
//Do what you want with the main window
}

Nested Master Pages and Inheritance

I created a nested master page. The parent master page A inherits from System.Web.UI.MasterPage. The child master page B inherits from A.
I then created a web content page C which uses master page B, and inherits from System.Web.UI.Page.
From the web content page C I am able to access variables and methods from within both master pages. However the problem lies in accessing the parent master page variables and methods.
The problem is that a NullReferenceException is being raised. Variables and methods are not being initialised.
What is a possible solution?
public partial class ParentMasterPage : System.Web.UI.MasterPage
{
internal Button btn_Parent
{
get { return btn; }
}
}
public partial class ChildMasterPage : ParentMasterPage
{
internal Button btn_Child
{
get { return btn; }
}
}
public partial class WebContentPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
Button tempA = Master.btn_Child; //WORKS
Button tempB = Master.btn_Parent; //NULL REFERENCE EXCEPTION
}
}
A nested master page does not inherit it's parent master page's type. Instead it composes itself such that the NestedMasterType.Master property is an instance of the parent master page. The NestedMasterType type still inherits from System.Web.UI.MasterPage.
So this is right:
public partial class ChildMasterPage : System.Web.UI.MasterPage
This is wrong:
public partial class ChildMasterPage : ParentMasterPage
You would then access the (parent) Master of the (child) Master of a Page (that uses the child master) like this:
Button tempA = ((ChildMasterPage)this.Master).btn_Child;
Button tempB = ((ParentMasterPage)this.Master.Master).btn_Parent;
Note: This answer assumes that you mean that ChildMasterPage is a nested master page, that uses a Master directive similar to the below:
<%# Master MasterPageFile="~/ParentMasterPage.Master" Inherits="ChildMasterPage"...
A Page only has a reference to it's immediate master and it's variables, you would have to traverse up the object graph to the main master page i.e.
var parentMaster = (ParentMasterPage)Page.Master.Master;
parentMaster.SomeProperty = ...;
Alternatively, you could bridge the gap between the 2 by implementing the same property in your ChildMasterPage i.e.
internal Button btn_Parent
{
get { return ((ParentMasterPage)Master).btn_Parent; }
}
This would mean the code you currently have would work, however, it sort of defeats the purpose of having a main master page.

Categories

Resources