Dialog to mainframe data transfer (WPF) - c#

I have the problem with data transfer - i have a wpf application with a splash screen which is runs in App class before main frame is loaded. This Splash is a dialog and App is a static class - how is it possible to pass the data from splash dialog to mainframe maybe via App.. or there is other way?

An event could pass the data about.
public App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var splash = new Splash();
var main = new Main();
splash.SplashViewFinished += (s, data) => {
main.Data = data;
//code to show main..
};
//code to show splash...
}
}
public class Splash : Window
{
public event EventHandler<SplashDataArgs> SplashViewFinished;
}
public class SplashDataArgs: EventArgs
{
}
Or you could use the mediator pattern. Like the Messenger class in MVVM light
http://www.galasoft.ch/mvvm/
Handling Dialogs in WPF with MVVM
http://mvvmlight.codeplex.com/discussions/209338?ProjectName=mvvmlight

Related

Firing Events/Loading Data upon Windows Form initialization (MVC)

Okay, so I have a basic MVC setup for my windows form application. What I am trying to do upon starting the application is launch a splash screen on a separate thread, while the splash screen is showing, fire an event to have the controller load in my static database from the model, and upon completion of that to close the splash and launch the primary form.
However, I have come to learn that you cant manually invoke events from the constructor.... does anyone have a workaround for this?
Here is my splash form
public partial class SplashScreen : Form
{
//Delegate for cross thread call to close
private delegate void CloseDelegate();
//The type of form to be displayed as the splash screen
static SplashScreen splashScreen = null;
public SplashScreen()
{
InitializeComponent();
}
// A static entry point to launch SplashScreen.
static private void ShowForm()
{
splashScreen = new SplashScreen();
Application.Run(splashScreen);
}
static public void ShowSplashScreen()
{
// Make sure it is only launched once.
if (splashScreen != null)
return;
Thread thread = new Thread(new ThreadStart(SplashScreen.ShowForm));
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
// A static method to close the SplashScreen
static public void CloseForm()
{
if (splashScreen != null)
{
splashScreen.Invoke(new CloseDelegate(SplashScreen.CloseFormInternal));
}
}
static private void CloseFormInternal()
{
splashScreen.Close();
splashScreen = null;
}
}
Here is what I am doing in my main form
public partial class Map : Form, IMapView
{
// Dictionary to hold overlays
private static List<GMapOverlay> overlays = new List<GMapOverlay>();
// global variables to track status of buttons
private bool closedButtonStatus;
private bool titleButtonStatus;
/// <summary>
/// Fired upon starting application
/// </summary>
public event Action StartupEvent;
/// <summary>
/// view constructor
/// Creates a new real estate data map and loads in the county boundary data
/// </summary>
public Map()
{
SplashScreen.ShowSplashScreen();
StartupEvent?.Invoke();
SplashScreen.CloseForm();
closedButtonStatus = false;
titleButtonStatus = false;
InitializeComponent();
loadMap();
}
/// <summary>
/// Loads the map and centers it over the united states, with desired default size metrics
/// </summary>
private void loadMap()
{
// Initialize map:
gmap.MapProvider = GMap.NET.MapProviders.GoogleMapProvider.Instance;
GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerOnly;
// Center map over the US
gmap.Position = new PointLatLng(40, -98);
this.Size = new Size(1360, 665);
this.MinimumSize = new Size(1000, 600);
}
So the event I'm trying to invoke is "StartupEvent" in the Map constructor, however, it won't fire.
It is possible to set your primary forms opacity property to 0%.
When you launch your program the primary form will launch but not be visible.
You can then display your splash screen from a primary form event, something like the 'Load' event. You can also launch your database load, etc.
Once you have achieved whatever startup processing you require you can shutdown your splash screen form and set the opacity of your primary form to 100%, which will cause it to become visible.

Track dynamic form automcatically in winforms

I have an application having 2 forms that opens on application start and 3rd form is getting added on runtime.
I have an another class library that currently monitors the activities of a single form. The below code snippet is of application :-
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form[] f = new Form[2];
f[0] = new Form1();
f[1] = new Form2();
f[0].Show();
AppContext nvca = new AppContext(new Form1(), new Form2());
Application.Run(nvca);
}
AppContext class is in class library where I am trying to catch all the forms of the application whether it is static or comes at runtime :-
public class AppContext:ApplicationContext
{
public static Form[] AvailForms = null;
public AppContext(params Form[] forms)
{
AvailForms = forms;
UAction ua = new UAction();
foreach (Form f in forms)
{
for (int i = 0; i < f.Controls.Count; i++)
{
ua.setClickHandlerAsync(f.Controls[i]);
}
}
}
public void setClickHandlerAsync(Control item)
{
//Have to recursively get all the element to wrap the click listener.
item.MouseClick += ClickHandlerAsync;
}
private async void ClickHandlerAsync(object sender, MouseEventArgs e)
{
Console.WriteLine("Click Handler called");
}
}
I am searching for a way through which I can track all the forms that are either already added in application or added at runtime.
I have tried through ApplicationContext, but it failed to capture the win events like click, text change, form events even though all the event handlers has been set properly on it.
Any help would be appreciated.

Splash screen appears everytime the project's starting window is invoked..

I have implemented a splashscreen for my project, it works well as desired.. but in my project i have an option of logout for user,this displays start page where a different login is provided(which is the starting screen..i.e, "chooselogin.xaml"). So when the user clicks on "choose a different login" while he already selected one in the application.. again the splashscreen appears, which is not required and looks odd.
the following code is what i think leading to problem... guys
public partial class Chooselogin : Window
{
public Chooselogin()
{
new SplashWindow().ShowDialog();
InitializeComponent();
}
......
This code is my "App.xaml"..
<Application x:Class="WpfApplication1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Chooselogin.xaml">
<Application.Resources>
<ResourceDictionary Source="/Themes/ExpressionDark.xaml"/>
</Application.Resources>
The splash screen code is as follows..
public partial class SplashWindow : Window
{
Thread loadingThread;
Storyboard Showboard;
Storyboard Hideboard;
private delegate void ShowDelegate(string txt);
private delegate void HideDelegate();
ShowDelegate showDelegate;
HideDelegate hideDelegate;
public SplashWindow()
{
InitializeComponent();
showDelegate = new ShowDelegate(this.showText);
hideDelegate = new HideDelegate(this.hideText);
Showboard = this.Resources["showStoryBoard"] as Storyboard;
Hideboard = this.Resources["HideStoryBoard"] as Storyboard;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
loadingThread = new Thread(load);
loadingThread.Start();
}
private void load()
{
Thread.Sleep(1000);
this.Dispatcher.Invoke(showDelegate, "Loading assets...please wait");
Thread.Sleep(2000);
//do some loading work
this.Dispatcher.Invoke(hideDelegate);
Thread.Sleep(2000);
this.Dispatcher.Invoke(showDelegate, "Loading profiles..");
Thread.Sleep(2000);
//do some loading work
this.Dispatcher.Invoke(hideDelegate);
Thread.Sleep(2000);
this.Dispatcher.Invoke(showDelegate, "Loading Data... almost done");
Thread.Sleep(2000);
this.Dispatcher.Invoke(hideDelegate);
//close the window
Thread.Sleep(2000);
this.Dispatcher.Invoke(DispatcherPriority.Normal,
(Action)delegate() { Close(); });
}
private void showText(string txt)
{
txtLoading.Text = txt;
BeginStoryboard(Showboard);
}
private void hideText()
{
BeginStoryboard(Hideboard);
}
}
The splash screen is supposed to be opened at start of application.. please help guys..
How about something simple like this?:
public partial class Chooselogin : Window
{
private static bool isFirstTime = true;
public Chooselogin()
{
if (isFirstTime)
{
new SplashWindow().ShowDialog();
isFirstTime = false;
}
InitializeComponent();
}
...
}
Now it will only display the splash screen once.
I recommend reading this post by Kent Boogaart
Example from the post
"WPF provides a SplashScreen class. It is simple by design and addresses the main goal of splash screens: immediate feedback. By virtue of forgoing the WPF stack and instead relying on Windows Imaging Component (WIC) to display images, it provides the quickest path to getting a splash on the screen short of writing your own native bootstrapper."

Tray application : Create UI on main thread from background thread event handler

I'm playing around with a tray application. The application runs only in the System Tray and has no Windows Form associated with it. The application uses a ManagementEventWatcher and displays an alert window in certain scenarios.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new AppContext());
}
...
public class AppContext : ApplicationContext
{
private System.ComponentModel.IContainer _components;
private NotifyIcon _notifyIcon;
private ContextMenuStrip _contextMenu;
private ManagementEventWatcher _regWatcher;
public AppContext()
{
//Initialize context menu & tray icon
_regWatcher = new ManagementEventWatcher(query);
_regWatcher.EventArrived += new EventArrivedEventHandler(_regWatcher_EventArrived);
_regWatcher.Start();
}
void _regWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
Alert.Show("Alert!", "My Message", someParam);
}
}
...
public class Alert
{
public static void Show(string title, string message, string extraInfo)
{
new Alert(title, message, extraInfo).ShowDialog();
}
private Alert(string title, string message, string extraInfo)
{
InitializeComponent();
this.Icon = Properties.Resources._default;
this.Text = title;
this.label1.Text = message;
this.linkLabel1.Text = extraInfo;
}
}
Interestingly, it doesn't complain about not accessing the UI in a thread-safe way. I suppose because it only exists on this background thread. But later on when the Form tries to access the clipboard, it doesn't work because it is running on an MTA thread. So far, all the similar questions I have found already have a form to call Invoke on, or have the option of using a BackgroundWorker. What is the best way to create and display the Alert Form on the main thread in this case?
Thanks to Idle_Mind's link to Andy Whitfield's blog post I've arrived at a solution. I added a private global SynchronizationContext to the AppContext class. In the constructor I initialize it to an instance of a WindowsFormsSynchronizationContext. Then when the registry watcher's event occurs, I can Post the task back to the main thread.
public class AppContext : ApplicationContext
{
private SynchronizationContext _uiThreadContext;
...
public AppContext()
{
//Initialize context menu & tray icon
_uiThreadContext = new WindowsFormsSynchronizationContext();
_regWatcher = new ManagementEventWatcher(query);
_regWatcher.EventArrived += new EventArrivedEventHandler(_regWatcher_EventArrived);
_regWatcher.Start();
...
}
private void _regWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
...
_uiThreadContext.Post(new SendOrPostCallback(MyEventHandler), parameters)
}

C# WPF close new user control

I am new to c#. I have created main windows that I am adding usercontrols to switch between screens with command:
Switcher.Switch(new NewPage());
The class Switcher is:
public static class Switcher
{
public static MainWindow pageSwitcher;
public static void Switch(UserControl newPage)
{
pageSwitcher.Navigate(newPage);
}
public static void Switch(UserControl newPage, object state)
{
pageSwitcher.Navigate(newPage, state);
}
}
But how to I exit the user control? I wish to finish it (like back button). I can use:
Switcher.Switch(new PreviousPage());
but it will keep the new page in memory and will not release it.
Example of NewPage class:
namespace MyProject.Screens
{
public partial class NewPage : UserControl
{
public NewPage()
{
InitializeComponent();
}
private void back_button_Click_(object sender, RoutedEventArgs e)
{
//what to put here?
}
}
}
The framework does a lot of the heavy lifting for navigation for you, including the "back" operation that you're interested in.
Take a look at http://msdn.microsoft.com/en-us/library/ms750478.aspx
NavigationService.GoBack is what you'll use.
In the off-chance that you're working on a Windows Store App, let me know, since my answer will be different.
You should really try and use the standard Navigation services available with WPF. This will give you configurable oage caching and journalling.
http://msdn.microsoft.com/en-GB/library/ms750478(v=vs.100).aspx
Try this:
private void back_button_Click_(object sender, RoutedEventArgs e)
{
Window parentWindow = (Window)this.Parent;
parentWindow.Close();
}

Categories

Resources