How can I close and reopen a window in wpf? - c#

I have a wpf application with a button, which opens a new Window, where I want to determine some settings. See following code:
public partial class MainWindow : Window
{
private SettingsWindow SettingsWindow;
public MainWindow()
{
InitializeComponent();
}
private void settings_Click(object sender, RoutedEventArgs e)
{
if (this.SettingsWindow == null)
{
SettingsWindow = new SettingsWindow(); // No reentrace here !!!
}
SettingsWindow.Show();
SettingsWindow.Focus();
}
}
However, when I close the SettingsWindow and want to reopen it from the MainWindow, the whole application freezes.
I thought the object would be destroyed at closing and thus initialized newly inside the if-clause.
Do I have to do an override in the SettingsWindow's close routine or did I disregard something else?

You will want to track if the SettingsWindow has been closed. Otherwise you are re-showing a window that has likely been closed and is disposed. Closing the window will not remove your reference to it.
public class SettingsWindow : Window
{
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
this.IsClosed = true;
}
public bool IsClosed { get; private set; }
}
public partial class MainWindow : Window
{
private SettingsWindow settingsWindow;
private void settings_Click(object sender, RoutedEventArgs e)
{
if (this.settingsWindow == null || this.settingsWindow.IsClosed)
{
this.settingsWindow = new SettingsWindow();
}
this.settingsWindow.Show();
this.settingsWindow.Focus();
}
}

Related

Affect to elements of owner window

This app consists from 2 windows; there is the Label in owner window, indicator1 name assigned. The method IndicatorOn() must to change the label's appearance, however it happen only if to call IndicatorOn() from the same window (Main Window) and zero effect if to call it from the other window like in my app. I tried to debug - everything seems all right: the program successfully enter to case 1 block and exit it, just the commands related with indicator1 has been ignored...
public partial class MainWindow : Form {
public MainWindow() {
InitializeComponent();
}
private void MainWindow_Load(object sender, EventArgs e) {
ChildWindow childWindow = new ChildWindow();
childWindow.Owner = this;
childWindow.Show();
}
public void IndicatorOn (byte indicatorNumber) { // assume that it cout is small
switch (boothNumber) {
case 1:
indicator1.ForeColor = System.Drawing.Color.Black;
indicator1.BackgroundImage = ExamopleProject.Properties.Resources.IndicatorActive;
indicator1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
break;
}
// ....
}
}
public partial class ChildWindow : Form {
MainWindow mainWindow;
public ChildWindow() {
InitializeComponent();
mainWindow = new MainWindow();
}
private void Button1_Click(object sender, EventArgs e) {
}
}

c# between windows form send data [duplicate]

In this example, MainWindow has a button that opens Window2.
Window2 has a button that writes "Hello, World!" to MainWindow textblock.
Project source: https://www.dropbox.com/s/jegeguhycs1mewu/PassData.zip?dl=0
What is the proper way to pass data from Window2 to MainWindow?
private MainWindow mainwindow;
public MainWindow mainwindow { get; private set; }
public Window MainWindow { get; set; }
private object mainwindow { get; private set; };
private MainWindow mainwindow = ((MainWindow)System.Windows.Application.Current.MainWindow);
this.mainwindow = mainwindow;
MainWindow
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// Open Window 2
private void buttonWindow2_Click(object sender, RoutedEventArgs e)
{
Window2 window2 = new Window2(this);
window2.Left = Math.Max(this.Left - window2.Width, 0);
window2.Top = Math.Max(this.Top - 0, 0);
window2.ShowDialog();
}
}
Window 2
public partial class Window2 : Window
{
private MainWindow mainwindow;
public Window2(MainWindow mainwindow)
{
InitializeComponent();
this.mainwindow = mainwindow;
}
// Write Message to MainWindow
private void buttonMessage_Click(object sender, RoutedEventArgs e)
{
mainwindow.textBlockMessage.Text = "Hello, world!";
}
}
The 'proper' way usually depends on what your needs and circumstances are. But in general, using a delegate to pass data between windows is a common and standard practice.
Lets say the data you want to pass is a string. In your Main window, you want to create a delegate that lets you pass a string. Then you create an instance of that delegate type and subscribe a method that matches. Then when you open your secondary window, you pass that delegate to your secondary window.
public delegate void DataTransfer(string data);
public partial class MainWindow : Window
{
public DataTransfer transferDelegate;
public MainWindow()
{
InitializeComponent();
transferDelegate += new DataTransfer(DataMethod);
}
public void DataMethod(string data)
{
// Do what you want with your data.
}
private void button1_Click(object sender, EventArgs e)
{
Window2 win = new Window2(transferDelegate);
win.Show();
}
}
Now, when you invoke that delegate in your secondary window, the DataMethod() of your Form1 gets called, and so you can pass information between windows.
Your secondary window implementation should look like this:
public partial class Window2 : Window
{
DataTransfer transferDel;
public Window2(DataTransfer del)
{
InitializeComponent();
transferDel = del;
}
private void button1_Click(object sender, EventArgs e)
{
string data = "Hello, World!"; // Your string data to pass.
transferDel.Invoke(data);
}
}
As you can see, when you invoke the delegate that was passed, it calls the corresponding method in your main program.
One stand out advantage of this method is that you don't need to pass an instance of MainWindow to your Window2, you simply use delegates and subscribed methods to pass data between the two instances of windows.
The answer you're looking for is very implementation-based and depends heavily on what you want Window2 as a class to do.
private MainWindow mainwindow;
This is acceptable.
public MainWindow mainwindow { get; private set; }
This would work but doesn't respect naming conventions because it's a property. Usually you'd use this for encapsulation of a field or for easy access to a computed value.
public Window MainWindow { get; set; }
This is not acceptable in your context because Window does not contain a textBlockMessage.
private object mainwindow { get; private set; };
This also wouldn't work for the same reason as above.
private MainWindow mainwindow = ((MainWindow)System.Windows.Application.Current.MainWindow);
This would work and would even let you not keep a field for the reference to the MainWindow instance in your Window2 instances. Still needs to get that MainWindow everytime you click the button however.
Another interesting way to do what you're doing however is to simply pass the handler to the child windows at instanciation:
MainWindow
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// Open Window 2
private void buttonWindow2_Click(object sender, RoutedEventArgs e)
{
Window2 window2 = new Window2(); // No need to give a reference to the child window anymore
window2.setClickHandler((obj, ev) => {
textBlockMessage.Text = "Hello, world!"; // Direct access to the textblock.
});
window2.Left = Math.Max(this.Left - window2.Width, 0);
window2.Top = Math.Max(this.Top - 0, 0);
window2.ShowDialog();
}
}
Window2
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
public void setClickHandler(RoutedEventHandler handler)
{
// The handler is given to the click event.
buttonMessage.Click -= handler;
buttonMessage.Click += handler;
}
}
And with that your Window2 class has no need to know MainWindow.
You could declare a delegate in Window 2 and pass a function that can be executed when the button is pressed in window 2.
public delegate void SendMessage(string Message);
public SendMessage mainWindowDel = null;
Make your constructor that accepts the delegate
public Window2(SendMessage del)
{
mainWindowDel = del;
}
create window 2 by passing a function as the parameter
public void showMessage(string Message)
{
if(!string.IsNullOrWhiteSpace(Message))
textBlockMessage.Text = Message;
}
private void buttonWindow2_Click(object sender, RoutedEventArgs e)
{
// Open Window 2
//Window2 window2 = new Window2(this);
Window2 window2 = new Window2(showMessage);
window2.Left = Math.Max(this.Left - window2.Width, 0);
window2.Top = Math.Max(this.Top - 0, 0);
window2.ShowDialog();
}
call the delegate when they press the button
// Write Message to MainWindow
private void buttonMessage_Click(object sender, RoutedEventArgs e)
{
mainWindowDel("Hello, world!");
}
You could probably set the datacontext of the MainWindow to an object that you could also pass to Window2 when it's created and set it's datacontext to the same object.
In that object could create a string property that could be used in both windows. And if you implement the INotifyPropertyChanged interface both windows would know when that string is updated.
Another Approach
MainWindow
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private bool DisplayText(string displayText)
{
txt_Main.Text = displayText;
return true;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Window2 win2 = new Window2(DisplayText);
win2.ShowDialog();
}
}
Window2
public partial class Window2 : Window
{
private Func<string, bool> mainWindowMethod;
public Window2(Func<string, bool> displayMethod)
{
InitializeComponent();
this.mainWindowMethod = displayMethod;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.mainWindowMethod("Hello World");
}
}

WPF , Switching between multiple windows without Disposing

I have 3 windows and I am able to switch between them fine. The problem i am running into is the windows aren't saving the data when hidden. I think somewhere they are getting disposed, but i'm not sure how. I have a textbox on two windows to test this. It worked fine when there was only two windows, but adding the third created this problem. Here is my main window.
public partial class MainWindow : Window
{
private AutoImport auto;
private DTLegacy dleg;
public MainWindow()
{
InitializeComponent();
}
public MainWindow(AutoImport parent)
{
InitializeComponent();
auto = parent;
}
public MainWindow(DTLegacy parent)
{
InitializeComponent();
dleg = parent;
}
private void btnAutoImport_Click(object sender, RoutedEventArgs e)
{
this.Hide();
if (auto == null) { auto = new AutoImport(); }
auto.Show();
}
private void btnDTLegacy_Click(object sender, RoutedEventArgs e)
{
this.Hide();
if (dleg == null) { dleg = new DTLegacy(); }
dleg.Show();
}
}
Window 1
public AutoImport()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Hide();
MainWindow main = new MainWindow(this);
main.Show();
}
Window 2
public DTLegacy()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Hide();
MainWindow main = new MainWindow(this);
main.Show();
}
I'm thinking the answer might be to create a window class of some sort, but i'm not sure what this would look like.
Why are you creating a new MainWindow instance each time? You're currently hiding it, so show it again instead of creating a new one.
Assuming it's the main Window of your application and AutoImport/DTLegacy are "child" windows, one solution would be to pass the MainWindow instance as parameter of the "child" windows, so you can call .Show() easily:
private MainWindow parent;
public AutoImport(MainWindow parent)
{
InitializeComponent();
this.parent = parent;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Hide();
this.parent.Show();
}

Cant get child window variable value on my parent window

Description - I have main window having status label which shows status in the form of connected and disconnected. When i create a object(parent window) in child window and set label status it wont be reflected in parent window. .I also tried, took a one Boolean variable and set to value 1 in child window code,but when i access that variable in parent window ,i got by default value that is zero.
/// My parent window code
public partial class MainWindow : Window
{
public CompSetting obj = new CompSetting();
public MainWindow()
{
InitializeComponent();
}
private void click(object sender, MouseButtonEventArgs e)
{
CompSetting compPortseting = new CompSetting();
compPortseting.ShowDialog();
}
private void button_Click(object sender, RoutedEventArgs e)
{
if (obj.flag == 1) // Here i get by defult value 0 . but already set to 1 on child window. In short cant access flag variable value.
{
LblPortStatus_lable.Content = "chetas";
}
else
{
LblPortStatus_lable.Content = "rahul";
}
}
}
// My child window code
public partial class CompSetting : Window
{
public int flag ;
public CompSetting()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
flag = 1;
}
}
private void click(object sender, MouseButtonEventArgs e)
{
if(obj != null)
{
obj.ShowDialog();
}
}
Do not create a new object, just use the existing one.
Extra
Instead of creating an instance of the child window consider creating an instance of a settings object. The child window would then get a reference to the settings object and modify it:
public partial class MainWindow : Window
{
public CompSetting settings = new CompSetting();
public MainWindow()
{
InitializeComponent();
}
private void click(object sender, MouseButtonEventArgs e)
{
var settingsDialog = new SettingDialog(settings);
settingsDialog.ShowDialog();
}
private void button_Click(object sender, RoutedEventArgs e)
{
if (settings.Flag == 1)
{
LblPortStatus_lable.Content = "chetas";
}
else
{
LblPortStatus_lable.Content = "rahul";
}
}
}
// My child window code
public partial class SettingDialog : Window
{
private CompSettings settings
public SettingsDialog(CompSettings settings)
{
this.settings = settings;
}
private void button_Click(object sender, RoutedEventArgs e)
{
this.settings.Flag = 1;
}
}
public class CompSettings
{
public int Flag;
}

Retry button access methods in another class

I have a button in a window that basically does a rerun through some code (retry button)
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void btnRetry_Click(object sender, RoutedEventArgs e)
{
//TODO retry function
//MainWindow.Connect();
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
I basically want to use the connect method in my main window class. However I can't do that unless it's a public static. However, if I do change Connect() to a public static, all the controls in it require to be static. I'm trying to minimize the amount of static controls I have; can anybody please help with a retry method?
Another solution is to make Window1.btnRetry visible to the parent form
public MainWindow : Window
{
private void ShowWindow1()
{
var window1 = new Window1();
window1.btnRetry.Click += OnRetryClicked;
window1.ShowDialog();
}
private void OnRetryClicked(object sender, EventArgs e)
{
// will be called when window1.btnRetry is clicked.
// retry the connection.
Connect();
}
}
First, you do need to make the method public (or internal) so that Window1 can use the method. However, do not make it static.
Instead, accept an instance of MainWindow in the Window1 constructor, and store it so that you can invoke the Connect() method on it later.
For example:
public partial class Window1 : Window
{
private MainWindow mainWindow;
public Window1(MainWindow mainWindow)
{
if (mainWindow == null) {
throw new ArgumentNullException("mainWindow");
}
this.mainWindow = mainWindow;
InitializeComponent();
}
private void btnRetry_Click(object sender, RoutedEventArgs e)
{
mainWindow.Connect();
}
// ...
}
Then, if constructing the instance from inside of MainWindow change your constructor invocation from new Window1() to new Window1(this).

Categories

Resources