So this sounds strange but I always get a stackoverflow exception when I execute 'this.Content' 3 times.
So I have a main window which stores all userControls so I dont have to create them always:
public partial class MainWindow : Window
{
CreateSessionWindow csw;
RateSessionWindow rsw;
CloseSessionWindow closesw;
MainMenuWindow mmw;
public MainWindow()
{
InitializeComponent();
csw = new CreateSessionWindow();
rsw = new RateSessionWindow();
closesw = new CloseSessionWindow();
mmw = new MainMenuWindow();
AllSessionWindows.csw = csw;
AllSessionWindows.rsw = rsw;
AllSessionWindows.closesw = closesw;
AllSessionWindows.mmw = mmw;
}
private void bttnStartProgram_Click(object sender, RoutedEventArgs e)
{
this.Content = AllSessionWindows.mmw;
}
}
public static class AllSessionWindows
{
public static RateSessionWindow rsw;
public static CloseSessionWindow closesw;
public static CreateSessionWindow csw;
public static MainMenuWindow mmw;
}
In my MainMenuWindow class I have a button and when I click on the button it changes the content:
public partial class MainMenuWindow : UserControl
{
public MainMenuWindow()
{
InitializeComponent();
}
private void bttnCreateSession_Click(object sender, RoutedEventArgs e)
{
this.Content = AllSessionWindows.csw; //here
}
}
And here is where I get usually the stackoverflowexception:
public partial class CreateSessionWindow : UserControl
{
public CreateSessionWindow()
{
InitializeComponent();
}
private void bttnGoBack_Click(object sender, RoutedEventArgs e)
{
this.Content = AllSessionWindows.mmw; //here I always get the exception
}
}
So no matter in which order I call this.Content (for eg. first mmw and than csw or csw and than mmw) I always get a stackoverflow Exception when I call it 3 times which you can see above. What could be the problem be?
The problem in your code is this.Content=... in UserControls (in this case this.Content is UserControl content not Window content). If you want to change content in the main window you should add property with MainWindow to class AllSessionWindows:
public static class AllSessionWindows
{
public static MainWindow MainWindow;
public static RateSessionWindow rsw;
public static CloseSessionWindow closesw;
public static CreateSessionWindow csw;
public static MainMenuWindow mmw;
}
In the MainWidnow constructor you must assign this property:
public MainWindow()
{
InitializeComponent();
...
AllSessionWindows.MainWindow = this;
}
And in UserControl you should use following code:
private void bttnCreateSession_Click(object sender, RoutedEventArgs e)
{
AllSessionWindows.MainWindow.Content = AllSessionWindows.csw;
}
Presented solution to this kind of problem by you is not the best solution. For this kind of problem, you can use Caliburn.Micro framework.
In the following link you can find a good tutorial:
http://www.mindscapehq.com/blog/index.php/2012/1/12/caliburn-micro-part-1-getting-started/
Your problem is described in part 5 and 6 of this tutorial.
Related
Im new at OOP and im wondering how i can say in my edit Class, get this textbox from the mainwindow and clear it. I tried this:
public partial class MainWindow : Window
{
Edit edit = new Edit();
public MainWindow()
{
InitializeComponent();
}
private void ClearBtn_Click(object sender, RoutedEventArgs e)
{
//TxtBox.Clear();
edit.Clear();
}
}
Edit class
public class Edit
{
MainWindow main = new MainWindow();
public void Clear()
{
main.TxtBox.Clear();
}
public Edit()
{
}
}
It's unclear to me why you would need to clear the MainWindow's text box from another class, as it's not practical in a real-world situation, but here you go:
public class Edit
{
public void Clear(MainWindow window)
{
window.TxtBox.Clear();
}
}
Another way to do it would be to pass the MainWindow into the Edit class's constructor, because I can see that you are instantiating Edit from the MainWindow class anyways.
public class Edit
{
private MainWindow _window;
public Edit(MainWindow window)
{
_window = window;
}
public void Clear()
{
_window.TxtBox.Clear();
}
}
if you wish to access controls of MainWindow from different classes you could use a similiar code:
MainWindow MWin = (MainWindow)Application.Current.MainWindow;
MWin.TxtBox.Clear();
In WPF I got one window in which there is a button and big text block, and the class in which I got a public method which sets the text to the text block in the window. The problem is, that this doesn't work and I quite don't understand why. The code looks like this:
In MainWindow.xaml.cs
private void GoButton_Click(object sender, RoutedEventArgs e)
{
Watcher watcher = new Watcher();
watcher.StoryMode();
}
And here is the public void StoryMode from class Watcher:
string text1 = #"C:/Users/Desktop/Folder/1.txt";
string mainText;
MainWindow mw = new MainWindow();
public void StoryMode()
{
mainText = text1;
mw.textBlock_story.Text = File.ReadAllText(mainText);
}
Every time when I click on the button, nothing happen and when I try to debug, I can see that it calls the function from the Watch class, but doesn't do anything at all. When I tried same code, but outside the Watch class, inside the MainWindow like this :
private void GoButton_Click(object sender, RoutedEventArgs e)
{
string text1 = #"C:/Users/Desktop/Folder/1.txt";
string mainText;
mainText = text1;
textBlock_story.Text = File.ReadAllText(mainText);
}
All works fine, but I that's not exactly something what I want in this case.
Could somebody explain me why does this happen and how to get a better solution for this problem?
Your window class needs to create an instance of the watcher class. It should then extract the text data from the watcher class.
class Watcher
{
public string mainText;
void StoryMode()
{
mainText = "Example Text";
}
}
public partial class MainWindow : Window
{
string texblock_story_text;
public MainWindow()
{
InitializeComponent();
}
void Get_Text()
{
Watcher MyWatcher = new Watcher();
texblock_story_text = MyWatcher.mainText;
}
}
I'm having trouble assigning the value of a variable from one class to another class. I have tried to do it in several ways but none works, the variable still has no value inside my method.
First Class:
namespace Simulador
{
public partial class Cidade : Window
{
private int QNTTodinho;
private void todinhobotao_Click(object sender, RoutedEventArgs e)
{
TodinhoBotaoo();
}
public void TodinhoBotaoo()
{
QNTTodinho += 1;
MainWindow Valor = new MainWindow(QNTTodinho);
}
}
}
Second Class:
namespace Simulador
{
public partial class MainWindow : Window
{
private int QNTTodinho;
public MainWindow(int qNTTodinho)
{
QNTTodinho = Convert.ToInt32(qNTTodinho);
}
private void Salgadinho_Click(object sender, RoutedEventArgs e)
{
Dinheiro22.Content = QNTTodinho.ToString();
}
}
}
I am guessing that the startup form for your application is
MainWindow. Which means you are creating an instance of MainWindow and running it as the main application window.
If this is the case, then creating another instance of MainWindow like what you are doing and passing the integer to it in the constructor wouldn't affect the actual main window. It is just setting the value in a copy of the MainWindow and directly scrapping that copy afterwards.
One way to fix that, although not the best practice, is to change the member you want to modify to be a static member, like that:
public partial class MainWindow : Window
{
public static int QntTodinho { get; set; }
public MainWindow()
{
}
private void Salgadinho_Click(object sender, RoutedEventArgs e)
{
Dinheiro22.Content = this.QntTodinho.ToString();
}
}
public partial class Cidade : Window
{
private int qntTodinho = 0;
private void todinhobotao_Click(object sender, RoutedEventArgs e)
{
TodinhoBotaoo();
}
public void TodinhoBotaoo()
{
this.qntTodinho += 1;
MainWindow.QntTodinho = this.qntTodinho;
}
}
Notice as well that I've done the following changes:
Used pascalCasing for private member
Used CamelCasing for public member
Get rid of Convert.ToInt32 as it is not needed
Things to consider with this solution are mainly thread safety and the lack of ways to notify MainWindow when the value changes.
I need help passing data from one WPF form to another. I have a main window with two other windows that will prompt the user for information. I want to end up with all the information in the first form so that I can store the data later on. The second form must return the Reservation and Room information when you click the OK button on the second form. The third form must return the Person information when you click OK.
public partial class MainWindow : Window
{
private string message;
public MainWindow()
{
InitializeComponent();
}
protected void Exit_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
protected void Create_Reservation_Click(object sender, RoutedEventArgs e)
{
Reservation PersonReservation = new Reservation();//Create a reservation instance
Room PersonRoom = new Room(); //Create an instance of a room
Person myPerson = new Person();//Create an instance of a person
CreateResRoom createReservationRoom = new CreateResRoom();//Create a instance of the CreateReservation WPF Form
createReservationRoom.Show();
Here it is supposed to set the room, reservation and person instance that I created equil to their corresponding instances in the CreateResRoom class.
I think the problem lies here, because it keeps continuing before it opens the CreateResRoom form.
PersonRoom = createReservationRoom.myRoom;
PersonReservation = createReservationRoom.myReservation;
}
}
That was my first class, the second and third will follow.
public partial class CreateResRoom : Window
{
Person myPerson;
public CreateResRoom()
{
InitializeComponent();
myReservation = new Reservation();
myRoom = new Room();
myPerson = new Person();
}
public Room myRoom
{
get;
set;
}
public Reservation myReservation
{
get;
set;
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void btnOk_Click(object sender, RoutedEventArgs e)
{
myRoom.RoomBeds = txtHeadCount.Text;
myRoom.RoomNumber = 1;
myRoom.RoomPrice = 20;
myRoom.RoomType = cboRoomType.Text;
myReservation.ResEndDate = dpEnd.ToString();
myReservation.ResStartDate = dpStart.ToString();
CreateRes createReservation = new CreateRes();
createReservation.Show();
//I think the same problem lies here that is in the MainWindow.
myPerson = createReservation.myPerson;
this.Close();
}
}
And the last class follows:
public partial class CreateRes : Window
{
public Person myPerson
{
get;
set;
}
public CreateRes()
{
InitializeComponent();
myPerson = new Person();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
private void btnOk_Click(object sender, RoutedEventArgs e)
{
myPerson.FirstName = txtFName.Text;
myPerson.LastName = txtLName.Text;
myPerson.IdNumber = Convert.ToInt32(txtIdNumber.Text);
myPerson.PhoneNumber = Convert.ToInt32(txtPhoneNumber.Text);
myPerson.AddressCity = txtAddressCity.Text;
myPerson.AddressStreet = txtAddressStreet.Text;
myPerson.AddressProvince = txtAddressProvince.Text;
myPerson.AddressPostalCode = txtAddressPostalCode.Text;
this.Close();
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
Just make a overload constructor which takes parameters of the window in which you want to retrieve.
Example:
Suppose we want a user to login from our MainWindow( i.e Login Window ) and we want to pass an int ID / string Email to our second form to retrieve data of logging user.
Than We have to first overload our second wpf form constructor. You can either make default constructor to do this or make an overload constructor for this work.
SecondForm:
public secondForm()
{
//Your Default Constructor Logic
}
public secondForm(string email_ )
{
//Your Overload Constructor Logic
}
Now in MainWindow from where we are logging and passing our EMail
MainWindow:
public void btnLogin()
{
//On Success
SecondWindow sw = new SecondWindow(txtBoxEMail.Content);
sw.Show();
}
A pattern you can use for this sort of thing is to have each form be responsible for creating the instance on ok click and then provide the object via a property get.
public partial class SomeForm: Window
{
public SomeClass MyProperty { get; private set; }
private void btnOk_Click(object sender, RoutedEventArgs e)
{
this.MyProperty = new SomeClass();
//additional setter logic here
this.Close();
}
}
Then you would access it from a parent form like this (notice the use of ShowDialog() http://msdn.microsoft.com/en-us/library/system.windows.window.showdialog(v=vs.110).aspx for easy checking of whether ok was clicked or not).
protected void Create_Reservation_Click(object sender, RoutedEventArgs e)
{
SomeClass myObj;
SomeOtherClass myOtherObj;
SomeForm myForm = new SomeForm();
if(myForm.Show().Value)
{
myObj = myForm.MyProperty;
}
SomeOtherForm myOtherForm = new SomeOtherForm();
if(myOtherForm.ShowDialog().Value)
{
myOtherObj = myOtherForm.MyOtherProp;
}
//save myObj & myOtherObj or whatever you need to do with them
Use the "normal way", here is a short overview.
First create a Data Context:
public class DC_Reservation() : INotifyPropertyChanged {
protected Reservation _PersonReservation ;
public Reservation PersonReservation {
get { return _PersonReservation ; }
set {
_PersonReservation = value;
NotifyPropertyChanged("PersonReservation ");
}
}
protected Room _PersonRoom ;
public Room PersonRoom {
get { return _PersonRoom ; }
set {
_PersonRoom = value;
NotifyPropertyChanged("PersonRoom");
}
}
protected Person _myPerson ;
public Person myPerson {
get { return _myPerson ; }
set {
_myPerson = value;
NotifyPropertyChanged("myPerson ");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged( string PropertyName ) {
if ( PropertyChanged != null ) {
PropertyChanged( this, new PropertyChangedEventArgs( PropertyName ) );
}
}
}
In the MainWindows you can assign and use the dataContext :
public partial class MainWindow : Window {
DC_Reservation dataContext {
get { return DataContext as DC_Reservation; }
}
private string message;
public MainWindow() {
InitializeComponent();
DataContext = new DC_Reservation();
}
protected void Create_Reservation_Click(object sender, RoutedEventArgs e) {
dataContext.PersonReservation = new Reservation();//Create a reservation instance
dataContext.PersonRoom = new Room(); //Create an instance of a room
dataContext.myPerson = new Person();//Create an instance of a person
CreateResRoom createReservationRoom = new CreateResRoom();//Create a instance of the CreateReservation WPF Form
// I'm not sure whether the next line is required.
createReservationRoom.DataContext = DataContext;
createReservationRoom.Show();
}
}
You can assign the DataContext in the constructor, but I think the better way is to define the DataContext in the MainWindow, in the other windows you can use the DesignContext:
<Window.DataContext>
<local:DC_Reservation />
</Window.DataContext>
So you can use the same DataContext over all forms ...
With DataBindings you can bind the input to the field:
<TextBox Text="{Binding FirstName, Path=myPerson, Mode=TwoWay}" />
I found another answer that Zarathos posted Jan 16 '13 at 21:43
for a different question
Use a public static class and access it from anywhere.
public static class Globals
{
public static String s_Name = "Mike"; //Modifiable in Code
public const int32 VALUE = 10; // unmodifiable
}
Then you can use it anywhere, provided you are working on the same namespace
string name = Globals.s_Name;
I've got an experience in designing websites with ASP.Net MVC.
I want now to be able to deal with WPF. So, I'm developping a tiny App to learn a few topics like threading, filestreams, and so on.
But, my problem seems really basic :
I've got on my main window a button that fires an action which calls another window. The new windows'aim is to get 2 strings and 2 doubles, to send them back to the main window.
My problem is, that the main window is not launched that way :
MainWindow m = new mainwindow;
And I'd like to do something like :
m.someVariable = somethingFromMySecondWindow.
So, I've tryed to set the main window static, but I got lots of errors, so I removed the "static".
I can't access variables from my second window, or any public method.
I don't know if it is needed, but here is the c# code i've already written.
mainWindow :
namespace FlightPlanningDraft1
{
/// <summary>
/// Logique d'interaction pour MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string _ACModel;
private string _ACIdentification;
private double _ACFuelConsumption;
private double _ACTotalFuel;
public MainWindow()
{
InitializeComponent();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
ChargementAvion c = new ChargementAvion();
c.Show();
}
public void Validation_Avion(string aCModel,string aCIdentification, double aCFuelConsumption, double aCTotalFuel)
{
_ACModel = aCModel;
_ACIdentification = aCIdentification;
_ACFuelConsumption = aCFuelConsumption;
_ACTotalFuel = aCTotalFuel;
}
}
}
My second window
namespace FlightPlanningDraft1
{
/// <summary>
/// Logique d'interaction pour ChargementAvion.xaml
/// </summary>
public partial class ChargementAvion : Window
{
public ChargementAvion()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//I don't know what to do here.
}
}
}
You can add an event to the second windows. Subscribe on it inside MenuItem_Click (MainWindow), and fire that event from Second window (Button_Click).
You can pass any value to you event.
public partial class ChargementAvion :Window
{
public event Action<string> OnDone;
private void Button_Click(object sender, RoutedEventArgs e)
{
if(OnDone != null)
{
OnDone("any string you want to pass");
}
}
}
and in MainWindow:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
ChargementAvion c = new ChargementAvion();
c.OnDone += ResultsHandler;
c.Show();
}
public void ResultsHandler(string result)
{
//do what you want ;)
}
I'd suggest you to look through this article. Just to be more familiar with events and delegates in C#.