I've an editor window opened. And, I've a requirement to check that if it fails to connect to database or, connection is broken when window is opened, the window should be closed.
var window = new EditorWindow(group);
window .KeyDown += (sender, args) =>{
if (args.Key == Key.Escape)
window .Close();
};
DialogHelper.ShowDialog(window);
And, for the change of database connection I've:
public dbState dbState
{
get { return dbState ; }
private set
{
dbState = value;
FirePropertyChanged("dbState ");
}
}
I'm new to WPF so any help would be appreciated. Thank you in advance.
If you are wiring things up directly, you would add code inside your EditorWindow class subscribing to the dbState property change event, and when that even fires, in your handler you would call this.Close() method to close the window. See http://msdn.microsoft.com/en-us/library/ms748948.aspx for more details.
A cleaner way to do it would be to use an MVVM library and take advantage of event aggregation. For example, this is how Caliburn.Micro does it: http://caliburnmicro.codeplex.com/wikipage?title=The%20Event%20Aggregator.
Related
Please provide the code snippet to create a tab instead of open a page in new window when click on the links in the webview2 - Edge in C# windows form.
Followed the below steps.
Drag the webview2 control on C# windows form and update the source property link: https://example.com
https://example.com site opened successfully in the webview2
click on few links in the site - https://example.com and it opens the new window and looking for open this one in the new tab instead of open it in new window
This event webView.CoreWebView2.NewWindowRequested never hit when debug the code. In case if this webView.CoreWebView2.NewWindowRequested event raised then no navigate method is available on webview class and its available on corewebview2 classs and getting the null reference exception if we use this.
For the sake of completeness, I was able to achieve the same thing thanks to David Risney's explanation. Unfortunately it didn't include any code, but I achieved this using 1.0.721-prerelease and Microsoft.WebView2.FixedVersionRuntime.87.0.664.66.x64:
Program.cs:
using System;
using System.Windows.Forms;
namespace TestApp1
{
static class Program
{
public static Microsoft.Web.WebView2.Core.CoreWebView2Environment WebView2Environment;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form1.cs:
using System;
using System.Windows.Forms;
namespace TestApp1
{
public partial class Form1 : Form
{
public Microsoft.Web.WebView2.Core.CoreWebView2Deferral Deferral;
public Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs Args;
public Form1()
{
InitializeComponent();
webView21.CoreWebView2InitializationCompleted += webView21_CoreWebView2InitializationCompleted_1;
}
private void CoreWebView2_NewWindowRequested(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
{
Form1 f = new Form1();
f.Args = e;
f.Deferral = e.GetDeferral();
f.Show();
}
private async void Form1_Load(object sender, EventArgs e)
{
if (Program.WebView2Environment == null)
Program.WebView2Environment = Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(#"C:\Users\Dragon\Downloads\Microsoft.WebView2.FixedVersionRuntime.87.0.664.66.x64", $#"C:\Users\Dragon\Desktop\Test{Guid.NewGuid()}").Result;
await webView21.EnsureCoreWebView2Async(Program.WebView2Environment);
webView21.Source = new Uri("http://www.google.com");
}
private void webView21_CoreWebView2InitializationCompleted_1(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
if (!e.IsSuccess) { MessageBox.Show($"{e.InitializationException}"); }
if (Deferral != null)
{
Args.NewWindow = webView21.CoreWebView2;
Deferral.Complete();
}
webView21.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
}
private void button1_Click(object sender, EventArgs e)
{
webView21.ExecuteScriptAsync($#"window.open('http://www.bing.com', '_blank');");
}
}
}
So the way this works is kinda weird: To spawn a new window, you can do it through JavaScript using ExecuteScriptAsync. In this case I'm opening a new window to bing.com. So, that makes a call to CoreWebView2_NewWindowRequested. For the event to pass and the code to work (otherwise it will freeze) it must go through it all. So, you cannot set the NewWindow property of the CoreWebView2NewWindowRequestedEventArgs inside the event that's currently happening.
The solution is to take the event data (args & deferral) to the new form, show it, and upon load and after the CoreWebView2 property of the control is not null / has initialized, by calling CoreWebView2InitializationCompleted, check if args/deferral are not null and then call the defer as Complete() (this is basically like a JS promise) AND here you can set the NewWindow property as CoreWebView2 has been initialized and therefore it's not null.
Hopefully this will answer your question and future readers. With this code, I was able to make it work.
There's no built in support for tabs in WebView2. However, you can intercept new windows with the NewWindowRequested event and provide your own CoreWebView2 to be that new window, and place that CoreWebView2 how you like in your UI. For instance the new CoreWebView2 could be placed in your UI to look like a new tab. (It sounds like that's what you're doing, but declaring it explicitly here just to ensure that I'm correctly understanding your scenario.)
Regarding the null WebView2.CoreWebView2 property, you can call EnsureCoreWebView2Async and await the returned task or you can set the WebView2.Source property and wait for the CoreWebView2Ready event to dispatch in order for the WebView2.CoreWebView2 property to be filled in. Its null before that.
Additionally, if you need to get the CoreWebView2 to fill in the NewWindowRequestedEventArg's NewWindow property, since the above steps for obtaining the CoreWebView2 from a WebView2 instance are both asynchronous, you'll need to call the NewWindowRequestedEventArg's GetDeferral method before starting async work in the NewWindowRequested event handler and call Complete on the Deferral once your async work is done in the NewWindowRequested event handler.
If you find cases where the WebView2 is opening new windows but the NewWindowRequested event isn't firing please open bugs at https://github.com/MicrosoftEdge/WebViewFeedback. What version of the SDK and the browser are you using with WebView2? There are some now fixed bugs with some scenarios opening new windows not firing the NewWindowRequested event.
i have a wpf application, i need to display a messagebox, the problem is that the message box is displayed for 0.5 second and doesn't even wait for user to click OK.
MainWindow.xaml.cs :
public partial class MainWindow : Window
{
public MainWindow()
{
//verifying application setting file to see if the connection is ok
string pathToApp = System.AppDomain.CurrentDomain.BaseDirectory + "settings.sts";
ApplicationSettings applicationSettings = new ApplicationSettings();
applicationSettings.ServerIp = "127.0.0.1";
applicationSettings.ServerDatabase = "test";
applicationSettings.ServerUserName = "root";
applicationSettings.MakeConnectionString();
foreach (char c in "")
{
applicationSettings.ServerPassword.AppendChar(c);
}
MySqlConnection connection = new MySqlConnection(applicationSettings.ConnectionString);
try
{
connection.Open();
}
catch (Exception e)
{
// here the message box shows for 0.5 second and closes immediately
MessageBox.Show(e.Message);
}
finally
{
connection.Close();
}
//display window
InitializeComponent();
}
i should also that am using a image as a splash screen, if this have a relation with the message box.
sorry this code is not yet completed. thanks in advance
Your problem stems from a known issue with WPF:
First, it happens when used with the splash screen. If you don't specify an parent for a message box, it assumes the splash screen is it's parent and is therefore closed when the splash screen closes. Second, even if you specify the parent as the MainWindow while in MainWindow's constructor, it still won't work since MainWindow doesn't have a handle yet (it gets created later on).
So, the solution is to postpone the invocation of the message box until after the constructor, and by specifying MainWindow as the parent. Here is the code that fixes it:
Dispatcher.BeginInvoke(
new Action(() => MessageBox.Show(this, e.Message)),
DispatcherPriority.ApplicationIdle
);
Here's a reference to the parent/splash issue:
http://connect.microsoft.com/VisualStudio/feedback/details/381980/wpf-splashscreen-closes-messagebox
In my situation (minimal tray icon app) there was no splash screen or MainWindow.
I found this solution from another SO question helpful:
var tempWindow = new Window();
var helper = new WindowInteropHelper(tempWindow);
helper.EnsureHandle();
MessageBox.Show(tempWindow, "Lorem Ipsum");
tempWindow.Close();
(I am not sure if the .Close() can be omitted)
In my application, I am overriding the OnClose event the way shown below. Since the application can take some time to perform SynchronizeLotsaStuff, I want to notify the user that application will soon close.
I tried with a MessageBox, but that blocks the continuation of the program, and also displays an "OK" button that is not desired.
I guess I would prefer something more characteristic, such as fading/graying the window, or even a "splash screen" for closing, but a regular messagebox would be fine too.
// MainWindow.xaml.cs:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
MessageBox.Show("Wait while application is closed...");
if (this.DataContext != null) {
var vm = this.DataContext as ShellViewModel;
// possibly long-running method
vm.SynchronizeLotsaStuff();
}
base.OnClosing(e);
}
UPDATE: Following Stijn Bernards advice, I put the MessageBox stuff inside a thread, but I haven't found (yes I googled) a proper way to terminate it. Even if Abort, the MessageBox keeps displaying after MainWindow has closed, until I click "OK" button.
// MainWindow.xaml.cs:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
var messagethread = new Thread(new ThreadStart(() => {
MessageBox.Show("Aguarde enquanto o aplicativo é encerrado...");
}));
messagethread.Start();
if (this.DataContext != null) {
var vm = this.DataContext as ShellViewModel;
// possibly long-running method
vm.SynchronizeLotsaStuff();
}
// UGLY UGLY UGLY (and doesn't work either)
messagethread.Abort();
base.OnClosing(e);
}
I have tried using the abort thread and to my suprises it isn't working.
And well I can say it doesn't look easy...
So I advice to look into this: click me
It's a good tutorial about how to create your own message box, which would then also help you with your problem of removing the ok button.
Cheers.
Im having an issue where i need to get my Classes to run a piece of code on exit.
Basically the code writes the Property's and Parameters to an XML file so they can be sent to the programmer to replicate the same settings as the client.
so i have created code like this on each of my classes.
~WorkspaceViewModel()
{
this.Save("Workspace");
}
my problem is that i cannot find a handler that will run before this destructor.
i have tried the following
//App.Current.Exit += new System.Windows.ExitEventHandler(ProgramExit);
//AppDomain.CurrentDomain.ProcessExit += new EventHandler(ProgramExit);
//App.Current.MainWindow.Closed += new EventHandler(ProgramExit);
//App.Current.Windows[0].Closed += new EventHandler(ProgramExit);
//AppDomain.CurrentDomain.DomainUnload += new EventHandler(ProgramExit);
//App.Current.MainWindow.Unloaded += new System.Windows.RoutedEventHandler(ProgramExit);
//System.Windows.Forms.Application.ApplicationExit += new EventHandler(ProgramExit);
//System.Windows.Application.Current.Exit += new System.Windows.ExitEventHandler(ProgramExit);
And saw something online about modifying the App class so i did this.
public partial class App : System.Windows.Application
{
public void OnExit()
{
this.OnExit();
}
public void App_Exit(Object sender, System.Windows.ExitEventArgs Args)
{
//Somelogic here
}
public App()
{
this.Exit += new System.Windows.ExitEventHandler(App_Exit);
}
}
could someone please help.
Are you using Windows Forms? If so, you can use the Closing event of the form. More reading: Form.Closing Event
Definition:
Occurs when the form is closing.
Example:
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if(MessageBox.Show("Do you want to exit?", "Your app title", MessageBoxButtons.YesNo) == DialogResult.No)
{
e.Cancel = true;
// cancel the closing
}
//otherwise the application will exit
}
You don't really need the if-statement, you can just call the Save method in this event and let the application exit afterwards.
You could do it this way (pseudocode)
Init();
window.Show();
Deinit();
You explicitly run initializers on application start and deinitiliazer on exit.
And in WPF it's done by using Application events, overrides or by a trick (setting Page build action for App.xml). In your implementation, you can't have constructor declared, because it's already generated (file App.g.i.cs). You can use application startup event though or simply set events in xaml.
As it turns out. all i needed to do was create a destructor on the App Class like this
public partial class App : Application
{
~App()
{
Administration.Model.DataBaseModel.GlobalCatalogue.ToFile();
}
}
Not really sure this is the best approach tho
Im still open to better ideas however.. thank you all.
My problem deals with the following 3 forms:
MainWindow.cs
SettingsWindow.cs
AuthenticationWindow.cs
Settings window contains information like "Ask for password during startup or not".
I call the Authentication Window from Settings Window in order to remove password (when the password is set).
I call the Authentication Window also during startup (when the password is set).
My Authentication Window interacts with the settings window using a Static variable(To say whether the authentication is successful or not).
But, in order to reuse the same code (that is, to call the same authentication window during startup), I am unable to tell the MainWindow whether the authentication is successful or not.
However, I must some how reuse the code.
My question is: Is it possible to notify the Child Window about whom the parent window is? If yes, Sample code please...
Hope my question is clear.
Kindly help!
I assume that Authentication Window is being used with ShowDialog() along the lines of:
AuthenticationWindow auth = new AuthenticationWindow();
if (auth.ShowDialog(this) == DialogResult.Ok)
{
// we know it was successful
}
Then within AuthenticationWindow when you've had success you'll call:
DialogResult = DialogResult.Ok;
Close();
to get the feedback above, or to signal that it failed by
DialogResult = DialogResult.Cancel;
Close();
Alternatively, you could set a property on AuthenticationWindow:
class AuthenticationWindow : Form
{
public bool Success { get; set;}
}
and set the value of Success appropriately from within the AuthenticationWindow code.
Lastly, if you want immediate feed back to be sent to your other windows, consider implementing an event:
class AuthenticationWindow : Form
{
public event Action<bool> SignalOutcome;
private OnSignalOutcome(bool result)
{
Action<bool> handler = SignalOutCome;
if (handler != null) handler(result);
}
}
Then you will have to subscribe to that event where you call the Authentication window:
AuthenticationWindow auth = new AuthenticationWindow();
auth.SignalOutcome += (outcome) => { /* do something with outcome here */ };
auth.ShowDialog(this);
ChildWindow c1=new ChildWindow();
c1.Owener=authenticationWindow;
c1.Show(); //or ShowDialog();
ChildWindow c2=new ChildWindow();
c1.Owener=anotherWindow;
c2.Show(); //or ShowDialog();
//to get the parent, use the property c.Owner
if(c.Owner is AuthenticationWindow) //AuthenticationWindow is the type of authenticationWindow instance
{
...
}