WPF starting a new Winform Cefsharp - c#

I've been working in WPF and trying to start a Winform from that area. The only solution is to open it as a ShowDialog(). Is this a bug or can we expect any problems in the future?
my other program is located in the same solution, but not the same namespace.
WindowsFormsApplication1.Form1 program2 = new WindowsFormsApplication1.Form1();
program2.ShowDialog();

I've just tested this, and it works for me:
public partial class MainWindow : Window
{
private Form winForm;
public MainWindow()
{
InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
winForm = new WinForm1();
winForm.Show();
}
}
I believe your problem is most likely due to your program2 going out of scope immediately after you try to call Show on it, which is closing it faster than you can see it. The reason ShowDialog works, is because it is a blocking call, keeps the window in scope and open until after it is closed.
Try declaring program2 as a field within the WPF Window class, instead of as a local variable. That will keep it in scope.

I found the problem... the reason program2.Show() was not working was becouse of Cefsharp during the launch of the second program via javascript the loading progress bar(Javascript) was not done loading. you can identify these problems with Cefsharp by tagging them in to
if (browser.CanExecuteJavascriptInMainFrame)
{
WindowsFormsApplication1.Form1 program2 = new WindowsFormsApplication1.Form1();
program2.Show();
}

Related

OpenForms won't run when I open a new form twice

I've run into some problems when opening a new form. The first time the new form is opened the code runs as expected, but if I close that form and open a new one right after, the code has a problem executing correctly.
Observe that this is not the main form, this is a separate form that is opened from the main form.
I suspect the problem is lying in the Application.OpenForms that I'm running from a separate class. But I really can't figure out why it wouldn't run the second time.
Here is an example (this code runs from a separate class.):
In the textbox (txtCFProjectNr) I wrote "0000-0000", it returns 0000-0000 the first time the form is opened, the second time it returns "2".
static frmCFNewProject newProjFrm = Application.OpenForms.OfType<frmCFNewProject>().FirstOrDefault();
public static void projectNrChanged()
{
bool format = Regex.IsMatch(newProjFrm.txtCFProjectNr.Text, #"[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]");
}
Here is how I open the new form
public void btnCFCreateNewStructure_Click(object sender, EventArgs e)
{
frmCFNewProject frm = new frmCFNewProject();
frm.ShowDialog();
}
When I restart the application, it works like a charm, until the form is closed and opened again.
I hope this explains enough.
I apologize for my bad English, this is not my native language. Thanks for your understanding.

CallContext – value disappears - WPF

I'm using Visual Studio 2015 and .Net
I’ve come upon a somewhat peculiar problem. I have a C# solution with two projects. One is a standard WPF application, the other a WPF User Control library. The WPF application project is the startup project.
In each project I have one window. In the startup project I open the window and set a value in the logical call context by using CallContext.LogicalSetData. This is done on load. I then close the window and open the window in the WPF User Control library. I populate one textbox with the value in the logical call context (using CallContext.LogicalGetData) and this works fine.
I have a button, which on click fires an event that populates another textbox with the same value from the logical call context – but all of a sudden this value is null.
I can make it work simply by changing the starting window to not do it’s “thing” on load but rather on a button event.
The startup window code:
public partial class MainWindow : Window
{
public MainWindow()
{
this.Loaded += OnLoaded;
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
CallContext.LogicalSetData("test", "value set onload");
TestWindow win = new TestWindow();
win.Show();
this.Close();
}
private void button_Click(object sender, RoutedEventArgs e)
{
CallContext.LogicalSetData("test", "value set on button event");
TestWindow win = new TestWindow();
win.Show();
this.Close();
}
}
As mentioned above, if I comment out the four lines in the OnLoaded method then it works fine.
The other window:
public partial class TestWindow : Window
{
public TestWindow()
{
InitializeComponent();
PreLoadedText.Text = CallContext.LogicalGetData("test") as string;
}
private void GetValue_Click(object sender, RoutedEventArgs e)
{
string eventTextText = CallContext.LogicalGetData("test") as string;
EventText.Text = eventTextText ?? "The value is null";
}
}
Btw. I tried using the AsyncLocal<T> class - but I just experienced the same problem.
Example solution can be found here:
Visual studio solution as zip file
Note - I'm not looking for a workaround (I have a couple), I'm looking for a reason why this happens.
It's because the instance of Thread.CurrentThread.ExecutionContext, which contains the DataStore of the CallContext, changes between the calls. You can check that if you give it a marker by using "Make Object ID" in the Visual Studio debugger.
Why does this happen? I have absolutely no idea. I tried to debug the .net Framework source without any luck.
As far as AsyncLocal<T> is concerned: It also uses the same Thread.CurrentThread.ExecutionContext and thus suffers from the same problem.
It doesn't happen if you use ThreadLocal<T> because that's using [ThreadStatic] and the Thread itself doesn't change.

Application.Startup event limitations (bug?)

It says, I can use Startup event for many things, like initialization, creating multiple forms, blablabla.
However, try to create a new WPF application and add this event handler:
private void App_Startup(object sender, StartupEventArgs e)
{
Window window = new Window();
}
And after closing main window your application will hang up in the memory. Pausing executing in VS at that moment will drop ugly crash call stack window with a lot of calls somewhere far away from my source code.
Any thoughts?
P.S.: I need to instantiate all of my windows for self-learning configuration purpose once. Should I use some other place?
Let me give a better example (example above is good to reproduce the problem, seems it's hard to understand what I am actually doing). I remove StartupUri and then:
private void App_Startup(object sender, StartupEventArgs e)
{
// un-comment this line to reproduce the problem:
// Window window = new Window();
// actual implementation will be
// Window1 window1 = new Window1();
// Window2 window2 = new Window2();
// Window3 window3 = new Window3();
// Window4 window4 = new Window4();
// ...
// start main window as usually
MainWindow mainWindow = new MainWindow();
mainWindow.Show();
}
And why do I need instances of windows (window1, ..2, ..3, ...)? Because their content will be inspected to create a list of controls for which I want to save configuration. Some of these windows will never be shown to the user (to example, if he is not admin), some of them are popups, some are editors, etc. So I do not want to display them. But at any application startup the configuration has to be created and saved. And I am looking now for the place to do so.
Surprisingly, using dedicated event Startup seems have some problems with creating multiple windows but not displaying them. Question is why and how to solve it.
Testing a bit more. Try this code and explain me, why application is closed without showing any window?
private void App_Startup(object sender, StartupEventArgs e)
{
Window window = new Window();
window.Close(); // closing without opening window
MainWindow mainWindow = new MainWindow();
mainWindow.Show();
//mainWindow = new MainWindow(); // can be un-commented, for absolutely no effect
mainWindow.Show();
mainWindow.Show();
mainWindow.Show();
mainWindow.Show(); // you will not see mainWindow at all, all Show doing nothing
}
More questions. What do I do?
Something what works, but smells:
private void App_Startup(object sender, StartupEventArgs e)
{
Window window = new Window();
MainWindow mainWindow = new MainWindow();
mainWindow.ShowDialog();
Shutdown();
}
Notice, calling ShowDialog (which will make event handler waiting for that window closing) and calling Shutdown right after.
It is still not clear what is the problem in the Startup event handler to create instances of some windows. Any ideas?
By doing this, the window you just created has become the main window: the one specified in StartupUri will only be created right after the start up event. By default, the main window must be closed for the application to shutdown. Since it's never shown, the user has no opportunity to do this and the application seems to hang forever. What you're seeing when the execution is paused is a normal message loop, there is no crash here. Add window.Show() to see your real 'main' window.
Remove the StartupUri attribute from your App.xaml if you decide to instantiate the main window manually. Alternatively, keep the attribute and instantiate the additional windows after the Loaded event from the main window has been fired.
I have solution, which seems pretty good to me. Idea is similar to winforms - do everything in the Main.
This, however, is a bit tricky in wpf (I used this question as a guide):
Remove StartupUri from App.xaml;
Set App.xaml property Build Action to Page (this sounds strange, but it works for desktop application). This will remove Main method from auto-generated classes (App.g.cs and App.g.i.cs).
Add Main method manually into Application:
.
public partial class App : Application
{
[STAThread]
public static void Main()
{
Window window1 = new Window();
Window window2 = new Window();
Window window3 = new Window();
// ...
MainWindow start = new MainWindow();
start.ShowDialog();
SomeOtherWindow next = new MainWindow();
next.ShowDialog();
}
}
Now I can directly control which window to show and when (program flow control), as well as there is no more bug with not-closing application when creating instances of windows without displaying them.
The suspicious things are this Page setting and that fact, what I do not instantiate Application, nor I call Run(). I do not know yet, if it will be a problem in the future. Would be nice to know it for sure.
It might be necessary to init application still (to load resources?), then
[STAThread]
public static void Main()
{
App app = new App();
app.InitializeComponents();
// ... the rest
// possibly app.MainWindow = start; or app.MainWindow = next;
// if only 1 window, then app.Run(new MainWindow());
}

Updating Form1's widgets by clicking Form2's button in Visual C# Windows Forms

I'm fairly new to Visual C# and I'm writing an GUI app with multiple forms. One form is main window, and the rest are some kind of option windows. When showing an option window, I need to load some data to it (for example a string to window's editbox), then edit it and return back to main window when closing option window. Is there any simple way I can achieve it?
I've found some solutions like, or c# event handling between two forms, but I can't really conform it to my needs. I was thinking about passing data in constructor, but how to get it back? I've found something about ShowDialog, but as I said I'm new to C# (started yesterday ^^) and don't know if I can use it.
Any ideas, please?
I found the following previous answer which outlines sending specific properties from the one form to another:
Send values from one form to another form
The using keyword will also ensure that the form is cleaned-up properly, here's a link to it's usage (pardon the pun...) : http://msdn.microsoft.com/en-us/library/vstudio/yh598w02.aspx
I've run into the same issue to be honest, and I have to say that prior to this discussion I would just pass the parent form itself to the child and alter it in that way. Such as:
ChildForm child = new ChildForm(this); //from the parent
and
public ChildForm(ParentForm parent)
{
this.parent = parent;
}
Probably not the best convention though, as you probably don't need to access that much from the parent as the child.
Thanks guys, I think I finally get it. Idle_Mind, your idea was the easiest in my point of view, so I decided to use it. If someone else has a problem like this, here's what I've coded:
In main window form: when button is clicked, a new form appears; after closing it, label1 shows the text typed in that form
private void Button1_Click(object sender, EventArgs e)
{
LoadDataForm loaddata = new LoadDataForm("initial value");
if (loaddata.ShowDialog() == DialogResult.OK)
{
label1.Text = loaddata.textBox1.Text;
}
}
In load data form: argument passed in form's constructor appears in textBox1; textBox1's Modifiers property has to be modified to "public"
public LoadDataForm(string initvalue)
{
InitializeComponent();
textBox1.Text = initvalue;
}
private void ApplyButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
Regards,
mopsiok

Is it absolutely safe to display a WPF window from a WinForms form?

I would like to display a WPF window from a windows forms application (.NET 3.5).
This code seems to work without any problem in a sample project:
public partial class WinFormsForm1 : Form
{
public WinFormsForm1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
WpfWindow1 w = new WpfWindow1();
w.Show();
}
}
The form is started from Main() as a normal Winforms form:
Application.Run(new WinFormsForm1());
This seems to me too easy to be true. Are there any shortcomings in this? Is this safe to do?
It has one serious shortcoming: the modeless WPF window would not get keyboard input.
The EnableModelessKeyboardInterop method call needs to be added before the WPF window is shown:
WpfWindow1 w = new WpfWindow1();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(w);
w.Show();
ElementHost resides in WindowsFormsIntegration.dll.
Further reading: http://msdn.microsoft.com/en-us/library/aa348549.aspx
Bottom line: it is.
We have pretty heavy application combining both WPF and winforms: windows, user controls, modal dialogs, you name it... and it's working in the medical market.
We've got into some dark corners, one is the infamous EnableModelessKeyboardInterop, another is having the WPF window be the child of the Winforms window, which you can read Here
It is really that simple. I can't think of any downside doing it this way.

Categories