Does the OnNavigatedTo() event know who navigated to it? - c#

If I have to, I will pass an arg to a page when I navigate to it, but is it necessary - is there a way to know which page called Navigate() without doing this?

Keep a static property in the Application object called PreviousPage. In the OnNavigatedFrom event of every page (or in the base class) set the PreviousPage to "this" (current page). In the OnNavigatedTo event, you can check that Application.PreviousPage property and use it how you see fit. This is the most effective way of accessing the previous page as there is no Frame.BackStack property in the framework for Windows Store Applications.

You could use GetNavigationState but it has some undesirable side-effects (it navigates away from the current page and the string is internal with no guarantees about how it might/might not change). I think you're best off passing it.
Calling this method will call Page.OnNavigatedFrom for the current
page using NavigationMode.Forward. GetNavigationState is usually
called when the application is being suspended, so the current page is
navigated away from.
Note:
The serialization format used by these
methods is for internal use only. Your app should not form any
dependencies on it. Additionally, this format supports serialization
only for basic types like string, char, numeric and GUID types.

I ran into this exact problem and Caleb's answer was very helpful. I just wanted to post some code to clarify how I used his solution.
DISCLAIMER I'm a bit (very!) new to C#, I'm sure there's a better way to do this, but I wanted to provide it as a starting point in case somebody else was looking for a bit more detail.
I created a global variable in the application's namespace to hold the previous page state:
public static class global_vals{
static object _previousPage;
public static object previousPage
{
get
{
return _previousPage;
}
set
{
_previousPage = value;
}
}
}
The OnNavigatedFrom method on each of my pages looks something like this:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
global_vals.previousPage = this;
}
And the OnNavigatedTo method checks the global variable like this:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (global_vals.previousPage.GetType().ToString() == "AppName.SomePage")
{
//do something
}
}

Related

Hidden calling of a function

Let's say I have two objects, Master and Slave.
Slave has a method named Init();. The thing about Init() is, that I need it to be virtual, because it contains user's initialization code, but I also need it to get called automatically when the Slave is added to Master's List. But the method must not be callable by the user, it has to be automatic.
The first thing that I tried is an event - create an event SlaveInitialized that a Slave object could handle in its OnSlaveInitialized handler. This wouldn't work though, because there's a lot of Slave objects and I have no control over the order in which they get created and need to be initialized.
The second thing that I tried is internal method - internal Init() would be called when the object is added to Master's list and all seems okay, until I realized that by doing so I cannot inherit the method in a public class.
So the third thing I did and that worked is this - I created an internal method called _Init() that simply calls a protected virtual Init(), which solved my problem.
Now I want to ask - do I just have a major strike of being stupid, because I am missing the painfully obvious solution here, or is this the way it's normally done? What is the proper way? I hope I got the point of what I'm asking across, I tried my best to explain the problem.
Thanks for any help
This is the gist of the code I now have. Its point is to have Init() invisibly and automatically called when you add any Slave object to the Master's list via Master.AddSlave();
public class Master
{
private List<Slave> _slaves;
public void AddSlave(Slave slave)
{
// Call the "hidden" init
slave._Init();
_slaves.Add(slave);
}
}
public class Slave
{
internal void _Init()
{
// Call the topmost overloaded method.
Init();
}
protected virtual void Init()
{
}
}
public class SuperSlave : Slave
{
protected override void Init()
{
// Now this method gets called automatically
// when Master.AddSlave adds this object.
}
}
As far as I can tell, there are two basic ways to do this.
Like you already tried, an internal InitInternal() method that calls a protected virtual Init()
A protected internal virtual Init(), which outside of your assembly automatically becomes a protected method.
While this doesn't answer the question the way you might want it, however I feel this could be an approperiate solution.
I would recommend throwing an InvalidOperationException if the Init method gets called multiple times.
Description: The exception that is thrown when a method call is invalid for the object's current state.
In my opinion it should not be your responsibility to police your objects from being abused, so long as documentation is written properly, your objects properties and method names describe what they do, it should be enough for most users (developers) consuming your code to understand how it works.
For those who decide to call Init themselves and then add to the Master object, you can throw that exception so they will know that their method for using the class is incorrect.
EDIT:
Naming the method OnInit might be a good idea, that way the user of the class has an indication that it should not be directly called by themselves.

Are class level variables/objects acceptable?

I have a simple web site built with asp.net. It typically only has 1 or 2 users at one time. My question is, is it ok to instantiate a class at the class level or should I be instantiating for each method. Here is an example. I have a class named Host with a name field and mac field. In my code behind for a specific page Is it ok to do this:
public partial class addhosts : Page
{
private Host host = new Host();
private HostDal dal = new HostDal();
protected void myMethod()
{
host.Name = "myname"
host.Mac = "mymac"
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
dal.AddHost(host)
}
}
First, what you are referring to are more typically referred to as global versus local variables.
In the simple case that you have listed, it would be better to create the variable on the submit click. The reason is if a user loads the object, but never calls the submit click, then you have instantiated the host object in memory when there was no need.
However, as many have said, it should not really matter one way or the other here. But, again, this is a simplistic example. Global variables can be dangerous and are often avoided as they can be modified from anywhere in your class. If one method expects a certain value that is then overrode, this can cause difficult to debug issues in more complex examples
Here is a wikipedia article that reiterates my above point:
They are usually considered bad practice precisely because of their
non-locality: a global variable can potentially be modified from
anywhere (unless they reside in protected memory or are otherwise
rendered read-only), and any part of the program may depend on it
To get rid of the globals, you could do this (using object initializers)
protected void btnSubmit_Click(object sender, EventArgs e)
{
var host = new Host
{
Name = "myname",
Mac = "mymac"
};
dal.AddHost(host)
}
It's completely OK to have user specific data as fields inside an ASP.Net Page instance. Every visit to a page creates a new instance of the Page class hence you'll not end up in a situation where data is incorrectly shared between users
It shouldn't matter.
Each request to your page is separate and has no knowledge of other requests therefore there is no chance of there being a "conflict" with other requests.
It's perfectly fine, since for each user new class is created (ASP.NET by design). It's in separate thread also, so even static variables would be acceptable in this scenario.
Cheers, Ivan

C# Trigger a method after another method (defined in a third party dll) is completed

This may fall into the category of method extending, overriding or polymorphism (I'm new to C# and OO so forgive me, I'm still learning :-) ).
I have an app that is utilizing a 3rd party API. Within the API there is a method for right click+select action on a custom control (the control is an image viewer where a user can right click and cycle to another image that exists within the parent group).
In my limited understanding I would think one of these 2 things would need to happen (whether either one can be done or whether either one is a good solution is up in the air!)
I don't want to override the existing method, I just want to append to it somehow.
If there was a way I could detect when the specific event was triggered and completed, then call my method. Set up some kind of listener if thats available.
Thanks!!
As you didn't post any reference, I'll try to outline some ways.
if there is an event
CustomControl cc = yourCustomControl;
cc.SelectionCompleted += (sender, args) => { YourMethod() };
This is using an anomynous event handler using a lambda.
Another way would be:
public class Form1 : Form
{
public Form1()
{
this.cc.SelectionCompleted += HandlerSelectionCompleted;
}
public void HandlerSelectionCompleted(object sender, EventArgs e)
{
YourCustomMethod();
}
}
there is a method to override
public class YourCustomControl : CustomControl
{
public override void Selection()
{
base.Selection(); // first call the original method
// now do some custom stuff
}
}
You can not override that method: that's right, if it's not protected/virtual/abstract whatever, or if you can not derive from that component's class.
You can search the component for the events and guess (if there is no any documentation) which event is fired after your desired action. And actually execute the code in that event handle.
There could be other "hacking" tricks, but I personally would avoid to do something like that, if not for personal passion, but focus on reachitecturing my program, in order to fit the requirements and support that component, as much as I can.
Regards.
What you are describing is a tenant of Aspect Oriented Programming AOP. If you want to instrument a 3rd party .NET dll, I would recommend PostSharp http://www.sharpcrafters.com/solutions/logging

what WPF method can I use to set some properties on a control's first display?

I need to store my app window's size/position and state when the user closes the app and set them back when the user thereafter opens the app.
I did this easily using registry keys (is this even the best way to do?), but I'm wondering where I actually should put the code to set those properties.
I need to set them when the window first "appears" I think. But I have several methods that could be used in this case, namely:
Window.Show()
Window.Activate()
Window.ApplyTemplate()
Window.Arrange()
Window.ArrangeCore()
Window.ArrangeOverride()
Window.BeginInit()
Window.EndInit()
Window.Measure()
Window.MeasureCore()
Window.MeasureOverride()
Window.OnApplyTemplate()
Window.OnInitialized()
Window.OnRender()
Window.UpdateLayout()
I'm aware that most of them just are a bad idea (UpdateLayout() will be called waaaaaaay too often for instance). Idealy I'm looking for a method that will only be called once in the window's life so that I don't have to add a flag checking if this is the method's first call.
so which one would be the best in this case? and why?
side question: I put the code to save the values in Window.Close() (I'm overriding the method in my MyWindow class), But I could as well have put it in Window.OnClosing() or Window.OnClosed(). Does this make any difference in my case?
side question (bis): I also have to save a datagrid's column order, where should I put both "saving" and "loading" code in this case?
Ok, it seems to me you are treating WPF like you would an old-school WinForms application. You no longer need to monitor form events to retrieve information from the Forms Properties. A majority of WPF Control properties are something known as a Dependency Property.
Amonst some of the clever things dependency properties introduce is Data Binding.
If you then consider writing the application with an MVVM Architecture you will quickly be able to work the following out yourself... =)
In the View*1, you can create either Dependency Properties, or standard properties and implement INotifyPropertyChanged, which hold the Size/Layout/Position/etc. Then bind the form's properties (in xaml or code) to the View's Properties. You can then implement any functionality you like for storing/retrieving the defaults and have automatic updates when the form is changed by simply adapting the Get/Set of the properties in the view.
As a quick example on the Windows' Title:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding Path=DisplayName}"
WindowStartupLocation="CenterScreen" >
<Grid>...</Grid>
</Window>
An example implementation of the view:
public class SampleView : System.ComponentModel.INotifyPropertyChanged
{
public event PropertyChangedEventHandler System.ComponentModel.INotifyPropertyChanged.PropertyChanged;
public delegate void PropertyChangedEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e);
private string _Title;
public string Title {
get {
if (_Title == null) {
_Title = My.Settings.MainWindowTitle;
}
return _Title;
}
set {
_Title = value;
if (!(_Title == My.Settings.MainWindowTitle)) {
if (PropertyChanged != null) {
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Title"));
}
My.Settings.MainWindowTitle = Title;
My.Settings.Save();
}
}
}
}
EDIT: Regarding how best to store user preferences, I wouldn't recommend the registry though, it's far from unheard of. The registry nowadays is packed full of settings that, in my opinion, the registry wasn't really designed for. Consider using application settings set to a user scope. That will handle most of the subleties of where and how the data is stored/retrieved and provide a nice type safe interface for you.
*1 I personally prefer to try and bind everything to the ViewModel and have almost totally dumb Views; though I do know there are plenty of valid cases for the Views having code. I wouldn't say the Size/Layout/etc is really a Business Logic Concern and isn't something I've concerned myself with up to now, so this should probably be handled in the View itself.
EDIT 2 - A quick example of User/Application scope settings:
Here is a quick picture of the settings I added to the project:
The following code attempts to use both the application and user scoped settings.
NB: Application Scope Settings are ReadOnly at runtime
public class SettingsExample
{
private Form1 frmMain = new Form1();
public void Main()
{
frmMain.BackColor = My.Settings.DefaultBackColour;
}
public void UserLoggedIn()
{
frmMain.BackColor = My.Settings.UserBackcolour;
}
public void UpdateUserBackcolour(System.Drawing.Color newColour)
{
My.Settings.UserBackcolour = newColour;
My.Settings.Save();
}
public void UpdateDefaultBackcolour(System.Drawing.Color newColour)
{
My.Settings.DefaultBackColour = newColour;
// Compiler Error
// This property is read only because it is an application setting
// Only user settings can be changed at runtime
}
}
First off, you forgot about
Loaded event - occurs when the element
is laid out, rendered, and ready for
interaction. (Inherited from
FrameworkElement.)
There is no one simple answer. Scenario may vary whether it'a child "dialog-like" window (then I would just set the size a line before Show() ), a new instance of the same window or a new instance of the app.
I will argue that UpdateLayout() is a bad idea. Actually, it's a very good idea. For example:
private bool m_onStart = true;
public MainWindow()
{
InitializeComponent();
this.LayoutUpdated += new EventHandler(MainWindow_LayoutUpdated);
}
void MainWindow_LayoutUpdated(object sender, EventArgs e)
{
if (m_onStart)
{
m_onStart = false;
Dispatcher.BeginInvoke(() =>
{
//Start App
}
);
}
}
Even if it's called a thousand time per second (which is very unlikely) you won't even notice it and won't hurt the performance.
All in all, you can make a helper method that saves user preference and second the reads it. Since the task is view related and using MVVM and binding is an overkill for this, set the size in Loaded event (do it when all ctors, initialization and visual tree is done).
My Choice: I finally ended up putting the code to load the values from the registry in window.Show().
the reason I did this is because of 2 things:
I store the state of the window, (minimized/maximized) and the way WPF does it, I need to first set the width/height, then the maximized state (if needed), otherwise it messes up the layout. And if I don't set the width/height first, I loose them when I de-maximize the window thereafter. So I have to do things in this order precisely: Width + height and them state. (Also, this is necessary when working with multiple screens, otherwise you loose the screen you were working on). This means that some of the methods above are impractical (the "measure" ones for instance)
adding to this, if I put my code in most of the methods above-mentioned, I'll get a bad looking effect on first display: the window will first appear with its height and width set, in the middle of the screen, and then after a small delay, the window gets maximized.
putting the code in window.Show() managed to solve those 2 issues. I might have had the same result with one or more of the other methods, but I simply got fed-up with trying different configurations and ended up using the first one that gave me entire satisfaction.

How to have code in the constructor that will NOT be executed at design time by Visual Studio?

I have a method call in the constructor of my user control that does something that won't work at design time (connecting to a database), and Visual Studio just bailed out when I tried to add that control to the GUI designer.
Sure, I can factor out that code to a separate method, but I don't like the idea that every time I use that object I need to remember to execute a certain method which is essential to that object's function (that's what the constructor is for!).
Is there something like a preprocessor symbol that I can mark my code with so that Visual Studio won't try to execute that code at design time?
As others have stated, you can use the DesignMode property of the Component class. However, you will not be able to do this in the constructor of your control. The DesignMode property is always false in the constructor and methods called by the constructor. To get around this, re-factor your code to connect to the database in the OnLoad() callback. The DesignMode property is valid at that point. See here for the reasoning (look for the DesignMode section of the article).
I just ran across this blog entry that describes how to use the System.ComponentModel.LicenseManager.UsageMode property for doing the same thing. The blog describes an additional shortcoming of the DesignMode property when dealing with nested controls. Apparently, the UsageMode property doesn't have the same shortcomings and is available for use in the constructor. I cannot personally vouch for it, but might be worthwhile looking into.
In Windows Forms?
if (!DesignMode)
{
// code that shouldn't be executed at design time
}
As others have mentioned, this won't work in the constructor. It's often used in the Form.Load event.
Have a look at this
Component.DesignMode Property
I liked Michael Petrotta's approach for Windows Forms. If anyone wants to apply the same technique to WPF, simply use IsInDesignMode.
Example:
public SomeViewModel()
{
if (!IsInDesignMode)
{
DoWork();
}
}
public SomeViewModel()
{
if (!IsInDesignMode)
{
DoWork();
}
}
This code above if you are working on the actual UI that you are trying to work on. In a situation that you have something like this on a control, when you switch back to the designer for that control it's ok and no design time error. Now if you added that control that contains the code above to some other Form or another control via dragging it from the toolbox, it will show some design time errors.
This is the only code that worked for me, using WPF UserControl on a Windows Form.
private bool? inDesignMode;
public bool IsDesignMode
{
get
{
if (inDesignMode == null)
{
var prop = System.ComponentModel.DesignerProperties.IsInDesignModeProperty;
inDesignMode = (bool)System.ComponentModel.DependencyPropertyDescriptor
.FromProperty(prop, typeof(FrameworkElement))
.Metadata.DefaultValue;
if (!inDesignMode.GetValueOrDefault(false) && System.Diagnostics.Process.GetCurrentProcess().ProcessName.StartsWith("devenv", StringComparison.Ordinal))
inDesignMode = true;
}
return inDesignMode.GetValueOrDefault(false);
}
}

Categories

Resources