I'm attempting to create an object which will hold any values the application will need globally during its runtime. I thought i'd use App.xaml.cs as this is the heart of the application if I understand correctly as that code is run first and kept in memory.
Getting this error on the .inProgress part of the code at the bottom of this post:
'App' does not contain a definition for 'inProgress' and no extension
method 'inProgress' accepting a first argument of type 'App' could be
found (are you missing a using directive or an assembly reference?)
App.xaml.cs
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Startup
Window main = new MainWindow();
main.Show();
//Bind Commands
Classes.MyCommands.BindCommandsToWindow(main);
//Create runtime objects
var runtime = new runtimeObject();
}
public static explicit operator App(Application v)
{
throw new NotImplementedException();
}
}
/// <summary>
/// Global values for use during application runtime
/// </summary>
public class runtimeObject
{
private bool _inProgress = false;
public bool inProgress
{
get { return _inProgress; }
set { _inProgress = value; }
}
}
Here i'm trying to access the runtime object so that I can see if the application can be closes, bare in mind this may not be needed, but I would need to do similar tasks like this other than close the window.
Classes > Commands.cs
bool inProgress = (System.Windows.Application.Current as App).inProgress;
It looks like you need to add a property to access the runtime object. Currently you're just creating an instance in OnStartup method. Assign that instance to a property:
public partial class App : Application
{
public static runtimeObject runtime { get; set; };
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Startup
Window main = new MainWindow();
main.Show();
//Bind Commands
Classes.MyCommands.BindCommandsToWindow(main);
// Create runtime objects
// Assign to accessible property.
runtime = new runtimeObject();
}
public static explicit operator App(Application v)
{
throw new NotImplementedException();
}
}
Then access the property from your commands logic:
public static void CloseWindow_CanExecute(object sender,
CanExecuteRoutedEventArgs e)
{
if (App.runtime.inProgress == true)
{
e.CanExecute = false;
}
else
{
e.CanExecute = true;
}
}
Related
I have a hardware component that can be controlled via an SDK (a .DLL file referenced in the project).
I'm trying to implement a helper class that will handle the instantiation of the object and will serve the required object reference to each window that will require it.
This is how I create the object in the code behind of the window:
//private fields
SystemConnector myConn;
MyHardware mySystem; // this is the object i need a reference to
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
SystemDiscoverer SystemDiscoverer = new SystemDiscoverer();
SystemDiscoverer.Discovered += (sysInfo) =>
{
myConn = new SystemConnector(sysInfo.IPAddress);
if (myConn != null)
mySystem = new MyHardware(myConn);
};
SystemDiscoverer.Discover();
}
private void WindowBase_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (myConn != null)
myConn.Dispose();
if (mySystem != null)
mySystem.Dispose();
}
I want to move this logic into a helper class but I have some questions I couldn't find a solution for:
all of the Singleton examples I could find were for custom objects
and did not explain the use of a referenced object.
How to handle
the creation of the object since it's done inside of an event handler?
To handle the creation from an event handler, try:
LazyInitializer.EnsureInitialized(...)
It is threadsafe, so you should be able to initialize a static property for your singleton just fine.
MSDN article here:
http://blogs.msdn.com/b/jolud/archive/2010/04/02/initialization-of-shared-resources.aspx
An example, from the ASP.NET MVC 4 standard project template.
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute {
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext) {
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer {
public SimpleMembershipInitializer() {
Database.SetInitializer<UsersContext>(null);
try {
using(var context = new UsersContext()) {
if(!context.Database.Exists()) {
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
catch(Exception ex) {
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
I would wrap MyHardware class inside a singleton with an async method which wrap the SystemDiscoverer.Discovered Event:
public sealed class MyHardwareSingleton
{
static MyHardwareSingleton()
{ }
private MyHardwareSingleton()
{ }
private static readonly MyHardwareSingleton _myHardware = new MyHardwareSingleton();
private SystemConnector _myConn;
private MyHardware _mySystem;
public MyHardwareSingleton Instance
{
get { return _myHardware; }
}
public Task<MyHardware> GetHardwareAsync()
{
if (_mySystem != null)
{
return Task.FromResult(_mySystem);
}
var tcs = new TaskCompletionSource<MyHardware>();
SystemDiscoverer SystemDiscoverer = new SystemDiscoverer();
SystemDiscoverer.Discovered += (sysInfo) =>
{
myConn = new SystemConnector(sysInfo.IPAddress);
if (myConn != null)
{
mySystem = new MyHardware(myConn);
tcs.TrySetResult(mySystem);
return tcs.Task;
}
// This indicated that myConn came back null.
tcs.TrySetResult(null);
return tcs.Task;
};
// Make SystemDiscoverer run asynchrnously. We will await it so when it completes we will get the desired MyHardware instance.
SystemDiscoverer.DiscoverAsync();
return tcs.Task;
}
}
DiscoverAsync might be added inside the SystemConnector class and look like this:
public Task DiscoverAsync()
{
return Task.Run(() => Discover());
}
And then you can call it from your code via:
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
var myHardware = await MyHardwareSingleton.Instance.DiscoverAsync();
}
Of course, i didn't handle any exception handling / cancellation. This is just a sample of what could be done using TAP
Using VS 2013, C#, Windows Store App
I need to send one object from main Frame to new one and then work with it.
So i have main Frame, second Frame (for work with sended object) and DataModel.
Idea - is to display all data that i have at main frame, than choose one object, press on it, after pressing new Frame will appear and you can work with selected items in new frame.
Problem - how to send object from one Frame to another.
Currently i made next: create additional static class that with static property:
public static class GetCurrentEvent
{
public static Event CurrentEvent { get; set; }
}
So, at first i call to property of this class at main Frame, and save required object using it:
private void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
var clickedItems = (Event)e.ClickedItem;
GetCurrentEvent.CurrentEvent = new Event(
clickedItems.UniqueId,
clickedItems.Name,
clickedItems.Place,
clickedItems.Description,
clickedItems.Start,
clickedItems.End,
clickedItems.ImagePath
);
if (this.Frame != null)
{
this.Frame.Navigate(typeof(ChangeEvent));
}
}
After that i use this property in new Frame:
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
this.DataContext = GetCurrentEvent.CurrentEvent;
...
}
All works, but i think that it's not the perfect method.
So,the quesion how i can change code abowe for improving methods, or how i can send object from one class to another?
EDIT
Choosed varinat to send object from Frame to Frame - use Parameter:
var clickedItems = (Event)e.ClickedItem;
this.Frame.Navigate(typeof(ChangeEvent), clickedItems);
and then convert to required type in new Frame:
this.DataContext = (Event)e.NavigationParameter;
There are many many ways that this accomplished and this tends be an opinionated debate.
I typically opt for a simple solution, such as saving a state/session variable in a global accessible singleton. I call the singleton Global and keep it in the root of the namespace.
Example:
public sealed class Global
{
#region Singlton Contructor
Global() { }
static readonly Global instance = new Global();
public static Global Default
{
get { return instance; }
}
#endregion
#region Global Settings
public Settings Settings {get;set;}
private AuthenticatedUser _authenticatedUser;
public AuthenticatedUser AuthenticatedUser
{
get
{
return _authenticatedUser;
}
set { _authenticatedUser = value; }
}
private UserSession _currentSession;
public UserSession CurrentSession
{
get
{
if (_currentSession == null) _currentSession = UserSessionService.UserSessionFactoy();
return _currentSession;
}
private set { _currentSession = value; }
}
#endregion
}
CurrentSession in this case keeps track of the objects I want to pass frame to frame. And its easily accessed by using
Global.CurrentSession.SomePropertyOrObject
I am new to Windows phone programming and I am building a WP8 application and would like to access the "App" object from another module
eg:
ModuleA = where the 'public partial class App : Application' object lives
ModuleB = where 'DoThis.xaml' page lives
I have this in ModuleA:
public partial class App : Application
{
// .. most application stuff stripped out for brevity
private void Application_Launching(object sender, LaunchingEventArgs e)
{
// refresh the value of the IsTrial property when the application is launched
DetermineIsTrial();
string uriString = "/ModuleB;component/DoThis.xaml";
NavigationService.Navigate(new Uri(uriString, UriKind.Relative));
}
#region Trial
public static bool IsTrial
{
get;
// setting the IsTrial property from outside is not allowed
private set;
}
private void DetermineIsTrial()
{
#if TRIAL
// set true if trial enabled (Debug_Trial configuration is active)
IsTrial = true;
#else
var license = new Microsoft.Phone.Marketplace.LicenseInformation();
IsTrial = license.IsTrial();
#endif
#if DEBUG
// set to false if we are debugging....
//IsTrial = false;
#endif
}
#endregion
}
I don't know how to get the "App" object from ModuleA over to ModuleB so I can access it
I would like to do this in ModuleB
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
Debug.WriteLine("DoThis- OnNavigatedTo");
if( App.IsTrial ) // I would like this to be ModuleA's "App" object
{
// disable some functionality because trial mode...
}
// the rest cut for brevity
}
Thanks for your help !
You can always access the Application object via Application.Current.
Declare an interface in your module class:
public interface IMyApplication
{
void DoStuffInMainApp();
}
and implement it in your application class:
public partial class App : Application, ModuleB.IMyApplication
{
...
}
Now you can call a method in your application class from your module:
((IMyApplication)Application.Current).DoStuffInMainApp();
Since Module B can't know anything about Module A, you'll need to either create a shared Module C, or include all shared components in B.
I like a dependency-injection type of approach, where a given class (eg, the Page) calls for any external dependencies (eg, IsTrial), so that the owner of the class must inject all dependencies. I use something like this in my apps:
// settings class that the Pages will get access to
public interface ISettings
{
public bool IsTrial { get; }
}
// implementation of ISettings -- owned by the App class
public class Settings : ISettings
{
public bool IsTrial { get; set; }
}
// interface that a Page should inherit if it needs access to IsTrial
public interface IRequiresSettings
{
public ISettings { set; }
}
public class SomePage : PhoneApplicationPage, IRequiresSettings
{
public ISettings Settings { get; set; }
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if( Settings != null && Settings.IsTrial )
{
// disable some functionality because trial mode...
}
}
}
Notice that ISettings encapsulates the read-only behavior of IsTrial, so that the page sees the property as read-only.
There is one more step, and that is to actually set ISettings. The App class should be responsible for this, by handling the RootFrame.Navigated event. It should check if the navigated-to page inherits IRequiresSettings, and set that property accordingly.
private Settings _settings = new Settings();
private void InitializePhoneApplication()
{
RootFrame.Navigated += RootFrame_Navigated;
}
void RootFrame_Navigated(object sender, NavigationEventArgs e)
{
if (e.Content is IRequiresSettings)
((IRequiresSettings)e.Content).Settings = _settings;
}
Edited: I deleted my "quick and dirty" approach, because #GerritFölster's answer is as quick and not dirty.
I have a WPF application. In one of the XAML I have used Name attribute like as follows
x:Name="switchcontrol"
I have to access the control/property in .cs file using this.switchcontrol
My question is, I need to access the control in static method like
public static getControl()
{
var control = this.switchcontrol;//some thing like that
}
How to achieve this?
this is not accessible in static method. You can try save reference to your instance in static property, for example:
public class MyWindow : Window
{
public static MyWindow Instance { get; private set;}
public MyWindow()
{
InitializeComponent();
// save value
Instance = this;
}
public static getControl()
{
// use value
if (Instance != null)
var control = Instance.switchcontrol;
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Instance = null; // remove reference, so GC could collect it, but you need to be sure there is only one instance!!
}
}
Some alternatives to Tony's method - you could pass in the window (or whatever xaml construct you are using) as a reference to the method, e.g.
public static void GetControl(MainWindow window)
{
var Control = window.switchcontrol;
}
if you are going to be passing several different derived types of Window, you could also do this:
public static void GetControl(Window window)
{
dynamic SomeTypeOfWindow = window;
try
{
var Control = SomeTypeOfWindow.switchcontrol;
}
catch (RuntimeBinderException)
{
// Control Not Found
}
}
Application c:\pinkPanther.exe is running and it is application i wrote in c#.
Some other application starts c:\pinkPanther.exe purpleAligator greenGazelle OrangeOrangutan and i would like not to start new instance of c:\pinkPanther.exe with these arguments, but to currently running c:\pinkPanther.exe register it and react to it somehow.
How to do it?
EDIT!!!: i'm very sorry about pinkPanther.exe and ruzovyJeliman.exe that caused the confusion - i translated question from my native language and missed it :(
This is assuming your application is a WinForms app, as that will make it easier to keep it open. This is a very simple example, but it will show you the basics:
Add a reference to Microsoft.VisualBasic.
Create an Application class inheriting from WindowsFormsApplicationBase. This base class contains built-in mechanisms for creating a single-instance application and responding to repeated calls on the commandline with new arguments:
using Microsoft.VisualBasic.ApplicationServices;
//omitted namespace
public class MyApp : WindowsFormsApplicationBase {
private static MyApp _myapp;
public static void Run( Form startupform ) {
_myapp = new MyApp( startupform );
_myapp.StartupNextInstance += new Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventHandler( _myapp_StartupNextInstance );
_myapp.Run( Environment.GetCommandLineArgs() );
}
static void _myapp_StartupNextInstance( object sender, Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e ) {
//e.CommandLine contains the new commandline arguments
// this is where you do what you want with the new commandline arguments
// if you want it the window to come to the front:
e.BringToForeground = true;
}
private MyApp( Form mainform ) {
this.IsSingleInstance = true;
this.MainForm = mainform;
}
}
All you have to change in Main() is call Run() on your new class rather than Application.Run():
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );
MyApp.Run( new MyMainForm() );
}
}
WindowsFormsApplicationBase has some other capabilities you can explore, as well.
To communicate with the other instance of the application, you need some sort of inter-process communication. Apparently, WCF is the recommended form of IPC in .Net. You can do that with code like this (using WPF, but WinForms would be similar):
[ServiceContract]
public interface ISingletonProgram
{
[OperationContract]
void CallWithArguments(string[] args);
}
class SingletonProgram : ISingletonProgram
{
public void CallWithArguments(string[] args)
{
// handle the arguments somehow
}
}
public partial class App : Application
{
private readonly Mutex m_mutex;
private ServiceHost m_serviceHost;
private static string EndpointUri =
"net.pipe://localhost/RuzovyJeliman/singletonProgram";
public App()
{
// find out whether other instance exists
bool createdNew;
m_mutex = new Mutex(true, "RůžovýJeliman", out createdNew);
if (!createdNew)
{
// other instance exists, call it and exit
CallService();
Shutdown();
return;
}
// other instance does not exist
// start the service to accept calls and show UI
StartService();
// show the main window here
// you can also process this instance's command line arguments
}
private static void CallService()
{
var factory = new ChannelFactory<ISingletonProgram>(
new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), EndpointUri);
var singletonProgram = factory.CreateChannel();
singletonProgram.CallWithArguments(Environment.GetCommandLineArgs());
}
private void StartService()
{
m_serviceHost = new ServiceHost(typeof(SingletonProgram));
m_serviceHost.AddServiceEndpoint(
typeof(ISingletonProgram),
new NetNamedPipeBinding(NetNamedPipeSecurityMode.None),
EndpointUri);
m_serviceHost.Open();
}
protected override void OnExit(ExitEventArgs e)
{
if (m_serviceHost != null)
m_serviceHost.Close();
m_mutex.Dispose();
base.OnExit(e);
}
}