I've got a subclassed UserControl that is the content for my main window. I added a DepedencyProperty to my usercontrol, of type ResizeMode, and the PropertyChanged callback sets the ResizeMode of the main window to the value correctly. It runs fine. I can set it from the code behind, or from the XAML, and it works correctly.
However, when I set it from XAML, the designer throws an Object reference not set to an instance of an object exception, on the code in the PropertyChanged callback that sets the window's resize.
<classes:MyUserControl ResizeMode="NoResize">
<...>
</classes:MyUserControl>
This is the callback. MainWindow is a reference to the parent window.
private static void OnResizeModeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
(o as MyUserControl).MainWindow.ResizeMode = (ResizeMode) e.NewValue;
}
public ResizeMode ResizeMode
{
get { return (ResizeMode) GetValue(ResizeModeProperty); }
set { SetValue(ResizeModeProperty, value); }
}
public static readonly DependencyProperty ResizeModeProperty =
DependencyProperty.Register("SizeToFit", typeof(ResizeMode), typeof(MyUserControl),
new UIPropertyMetadata(ResizeMode.CanResize, new PropertyChangedCallback(OnResizeModeChanged)));
I could ignore it, or set it in the code behind, but I don't really understand the reason for this error, and I would prefer to set it in XAML.
Can anyone shed some light?
Do you know exactly where the NullReferenceExceptoin is being thrown? For example, if you try this instead:
var uc = o as MyUserControl;
var mw = uc.MainWindow;
mw.ResizeMode = (ResizeMode)e.NewValue;
... then is the exception raised on the second line or the third?
My feeling is that MainWindow has not been assigned by the time ResizeMode is first given a value, so accessing MainWindow.ResizeMode is causing the error.
If that's the case, it's safe to ignore:
var mw = (o as MyUserControl).MainWindow;
if (mw == null) return;
But you might want to cache the value somewhere, and then assign it to MainWindow.ResizeMode when MainWindow gets assigned later.
OK, I think I found the culprit.
The MainWindow is set by App.Current.MainWindow.
Now from what I've read, the Current.MainWindow doesn't exist in Design time, and then when the OnResizeModeChanged methods fire during designtime, MainWindow.ResizeMode, boom! Exception!
I added this line to my methods:
if ((bool) (DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)) return;
I encountered another problem where my XAML suddenly couldn't load my usercontrol, due to me setting some properties on MainWindow in the constructor, added this:
if (DesignerProperties.GetIsInDesignMode(this))
return;
Related
I have an image button and I want to be disabled when the program starts and upon certain condition, it needs to be enabled.
Here is my code,
public Screen( ) { //constructor
ImageButton hints;
ImageButton.ImageButtonStyle hintsstyle = new ImageButton.ImageButtonStyle();
hintsstyle.up = skin.getDrawable("newrightbut");
hintsstyle.down = skin.getDrawable("newrightbut");
hintsstyle.pressedOffsetX = 1;
hints = new ImageButton(hintsstyle);
hints.setPosition(650, 35);
hints.setHeight(70);
hints.setWidth(70);
stage.addActor(hints);
hints.setTouchable(Touchable.disabled);
}
public void update() {
hints.setTouchable(Touchable.enabled);
}
But, the button is not getting disabled when the program starts and I even tested with button.setDisabled(true) method. It also doesn't work. Any idea why? Any help would be great!! Thanks
This issue is 5 months old now but I try to answer regardless.
ImageButton hints is declared within your constructor (So its scope is limited to the constructor).
The only way that you don't get a compilation error calling it from a method outside the constructor is if you have also declared it somewhere else within your class.
Conclusion: you must have declared it somewhere else in your application and any default, it is enabled.
I have FlipView (it's virtualized with Mode="Standard") with ScrollViewer, Image (inside ScrollViewer as DataTemplate). I set ImageOpened event handler on Image with such code:
private void Image_ImageOpened(object sender, RoutedEventArgs e)
{
var image = sender as Image;
double width = image.ActualWidth;
double height = image.ActualHeight;
var sv = image.Parent as ScrollViewer;
if (sv != null && width != 0 && height != 0)
{
var properZoom = ZoomUtilities.CalculateZoomFactor(width, height);
sv.MinZoomFactor = 0.3f;
sv.ChangeView(null, null, properZoom);
sv.MinZoomFactor = properZoom;
}
}
properZoom is always correct value. One out of the thousand times when I change item (swipe) or load page with this FlipView application crash with breakpoint on sv.ChangeView(..) and AccessViolationException exception is thrown. Does anyone know what could be the reason of such behaviour? Are there any restriction when I can call ChangeView method?
EDIT:
Forgot to mention - there is also DoubleTapped event handler on ScrollViewer which also calls ChangeView
I had the same AccessViolationException using .ChangeView(..). I noticed the exception was thrown when the ScrollViewer I wanted to manipulate had focus. For example when a user was dragging through the list or controlling the scrollbar with his mouse.
Disabling animations solved my problems. If you want to keep the animations you should look for a way to remove focus on the controls before changing the view. I guess the animated ChangeView tries to change a property that is locked because of the user input.
Hope this helps.
I had the same problem.
Solution to me: call inverse, from image object to parent got error.
Call normal path: objectscroolviewer.changeview, works no error.
Then:
var sv = image.Parent as ScrollViewer;
change to
var sv = ScrollViewerObject;
Get object to variable externally, not by internal reference of parent, and ignores sender parameter.
I'm trying to do something that's arguably a bad idea, but I think it's still possible. I'm trying to override how WP8 handles the Back Button and implement it myself. I theorize that if I:
The Plan
Only ever create one "Frame" and "Page" in the entire application
Always handle PhoneApplicationPage.BackKeyPress myself unless they were about to back out of the application.
The Repro
Here's a sample project that has the crash
The code
..then it should work. However, my attempts are being thwarted by Windows Phone. Here's the code:
// This basically happens on PhoneApplicationService.OnLaunched
_viewModelChanged.StartWith(ViewModel).Where(x => x != null).Subscribe(vm => {
var page = default(IViewFor);
var frame = RootVisual as PhoneApplicationFrame;
// Find the initial PhoneApplicationPage for the app
page = RxApp.GetService<IViewFor>("InitialPage");
// Depending on how we're being signalled (i.e. if this is cold start
// vs. resume), we need to create the PhoneApplicationFrame ourselves
if (frame == null) {
frame = new PhoneApplicationFrame() {
Content = page,
};
}
page.ViewModel = vm;
var pg = page as PhoneApplicationPage;
if (pg != null) {
pg.BackKeyPress += (o, e) => {
if (ViewModel.Router.NavigationStack.Count <= 1 ||
ViewModel.Router.NavigateBack.CanExecute(null)) {
return;
}
e.Cancel = true;
ViewModel.Router.NavigateBack.Execute(null);
};
}
// Finally, set Application.RootVisual
RootVisual = frame;
});
Sadness
This works great, until right after this code executes, where a DispatcherItem queued by the framework crashes the app:
System.NullReferenceException occurred
Message: A first chance exception of type 'System.NullReferenceException' occurred in Microsoft.Phone.ni.dll
Microsoft.Phone.ni.dll!Microsoft.Phone.Controls.PhoneApplicationPage.InternalOnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) Unknown
Microsoft.Phone.ni.dll!Microsoft.Phone.Controls.PhoneApplicationPage.Microsoft.Phone.Controls.IPhoneApplicationPage.InternalOnNavigatedFromX(System.Windows.Navigation.NavigationEventArgs e) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.RaiseNavigated(object content, System.Uri uri, System.Windows.Navigation.NavigationMode mode, bool isNavigationInitiator, Microsoft.Phone.Controls.IPhoneApplicationPage existingContentPage, Microsoft.Phone.Controls.IPhoneApplicationPage newContentPage) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.CompleteNavigation(System.Windows.DependencyObject content, System.Windows.Navigation.NavigationMode mode) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.ContentLoader_BeginLoad_Callback(System.IAsyncResult result) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.PageResourceContentLoader.BeginLoad_OnUIThread(System.AsyncCallback userCallback, System.Windows.Navigation.PageResourceContentLoader.PageResourceContentLoaderAsyncResult result) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.PageResourceContentLoader.BeginLoad.AnonymousMethod__0(object args) Unknown
[Native to Managed Transition]
mscorlib.ni.dll!System.Delegate.DynamicInvokeImpl(object[] args) Unknown
System.Windows.ni.dll!System.Windows.Threading.DispatcherOperation.Invoke() Unknown
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.Dispatch(System.Windows.Threading.DispatcherPriority priority) Unknown
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.OnInvoke(object context) Unknown
System.Windows.ni.dll!System.Windows.Hosting.CallbackCookie.Invoke(object[] args) Unknown
System.Windows.RuntimeHost.ni.dll!System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(System.IntPtr pHandle, int nParamCount, System.Windows.Hosting.NativeMethods.ScriptParam* pParams, System.Windows.Hosting.NativeMethods.ScriptParam* pResult) Unknown
So, I've solved this - my code was problematic because I didn't grok how WP8 works :) Here's what I understand now, which may also be wrong but I'll write it anyways
How your WP8 app is initialized:
The OS creates your App class via rehydrating App.xaml.cs
This means, your constructor gets run, and as part of that, you create a PhoneApplicationFrame
Creating a PhoneApplicationFrame seems to also set a global static variable (same thing happens with creating PhoneApplicationService in the App.xaml, it sets PhoneApplicationService.Current).
NavigationService then attempts to recreate a XAML View via a resource string (i.e. '/MainPage.xaml'). Either it will recreate the one that was previously tombstoned, or if not, it defaults to the one in your WMAppManifest (this is the part I didn't understand).
PhoneApplicationFrame.Navigated gets called by NavigationService - this is where you can actually start doing stuff, including most importantly, setting Application.RootVisual, which will send the Loading... screen away
PhoneApplicationService.Launched or PhoneApplicationService.Activated finally fires, once basically everything is set up, depending how your app was woken up.
Found the issue. Well, the tip of the iceberg.
The code of the InternalOnNavigatedFrom method is:
internal override void InternalOnNavigatedFrom(NavigationEventArgs e)
{
PhoneApplicationPage content = e.Content as PhoneApplicationPage;
string str = ((content == null) || (content.Title == null)) ? string.Empty : content.Title;
PerfUtil.BeginLogMarker(MarkerEvents.TH_ONNAVIGATEDFROM_PAGE, string.Format("{0},{1},{2}", (base.Title == null) ? "" : base.Title, e.NavigationMode, str));
this.OnNavigatedFrom(e);
PerfUtil.EndLogMarker(MarkerEvents.TH_ONNAVIGATEDFROM_PAGE, string.Format("{0},{1},{2}", (base.Title == null) ? "" : base.Title, e.NavigationMode, str));
DeviceStatus.KeyboardDeployedChanged -= new EventHandler(this.OnKeyboardDeployedChanged);
Task rootTask = ApplicationHost.Current.RootTask;
rootTask.OnVisibleRegionChange = (ITask.VisibleRegionChanged) Delegate.Remove(rootTask.OnVisibleRegionChange, new ITask.VisibleRegionChanged(this.OnVisibleRegionChange));
Task task2 = ApplicationHost.Current.RootTask;
task2.OnSipVisibilityChange = (ITask.SipVisibilityChange) Delegate.Remove(task2.OnSipVisibilityChange, new ITask.SipVisibilityChange(this.OnSipVisibilityChange));
this._lastSipHeight = 0.0;
this._dictionary = null;
}
After a bit of debugging, I concluded that neither e or Application.Current.RootTask were null. After scratching my head, I looked at the code of the KeyboardDeployedChanged event handler:
public static event EventHandler KeyboardDeployedChanged
{
[SecuritySafeCritical] add
{
if (KeyboardDeployedSubscription == null)
{
KeyboardDeployedSubscription = new SubscriptionHandler(DeviceTypes.KeyBoard);
}
KeyboardDeployedSubscription.Changed += value;
}
[SecuritySafeCritical] remove
{
KeyboardDeployedSubscription.Changed -= value;
}
}
This code is poorly written. If the remove part of the handler is called before the add, KeyboardDeployedSubscription will be null and an exception will be raised. To test my theory, I subscribed to the event in App's constructor:
public App()
{
// Global handler for uncaught exceptions.
UnhandledException += Application_UnhandledException;
DeviceStatus.KeyboardDeployedChanged += (sender, e) => { };
And sure enough, the exception was gone. Now, to understand why your code is triggering this issue, I backtraced to which part of the framework is supposed to subscribe to the event. The only candidate is the InternalOnNavigatedTo method.
Therefore, your issue is that OnNavigatedFrom is called even though OnNavigatedTo was never called.
Since you are strungling with the built-in auto navigation of Windows Phone to the page defined in WMAppManifest.xml, I tried to remove the auto navigation and it basically worked (no exception).
I just replaced
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
with
<DefaultTask Name="_default" />
Not sure if this solves your problem but it at least doesn't crash anymore.
So, I have successfully grabbed a value out of an XML document and set it into a separate class called "AddCommas." The trace functions have shown me that it sets properly.
For more details, my objective is to take the language indicator ("fr" for french or "en" for english), set it inside the appropriate class and into a variable I will use. Now, I am using this variable to be used in an if statement; which will help me format a number properly (commas, decimals, spaces) per the clients request.
However, my problem is when I try to get the value to use it. It always comes back as Null. I have placed traces all over my program trying to pinpoint when this happens, but I cannot find it. Here's the code...
The pull from the XML file and into the set (this works fine, but I am adding it for your benefit in case I missed something)
public var commaHold = new AddCommas();
localLanguage = xmlObj.localLanguage;
trace("localLanguage + " + localLanguage);
commaHold.setLanguage(localLanguage); // Set Language
//More code follows...
This is the set function istelf...
public function setLanguage(localLanguage:String){
langHold = localLanguage;
trace("Set Language = " + langHold); //This always shows a successful set
}
Now am I wrong in thinking that in AS3, once langHold in my AddCommas class has been set I should be able to use it without calling a get within the function I am using the If Statement in, right? Such as this?
var language = langHold;
if (language == "en"){
trace("Language is = " + language); // More code follows afterwards and as of now, this shows NULL
Now, I have attempted plenty of Get functions to add the language variable in the call itself to this function and it's always the same. Am I missing some fundamentals here?
Thank you very much for your time.
If you expect a string comparison you need to use quotes, unless en is a String variable since langHold is a String, like:
if (language == "en"){
Consider modifying the set function to use the as3 keyword like:
private var _language:String;
public function set language(value:String):void {
_language = value;
//do other stuff here if necessary, put a breakpoint on the line above
}
public function get language():String{
return _language;
//put a breakpoint on the line above
}
You should be able to see when any instance of your class has the property changed. The only other issue I can think of is it is not the same instance of the class and therefore doesn't share the property value you set earlier. In the debugger you can check the "hashCode" or "address" it shows for this to see if it changes when it hits the breakpoints.
Here's a sample Singleton structure in AS3 (this all goes in one file):
package com.shaunhusain.singletonExample
{
public class SingletonExample
{
private static var instance:SingletonExample;
public static function getIntance():SingletonExample
{
if( instance == null ) instance = new SingletonExample( new SingletonEnforcer() );
return instance;
}
/**
*
* #param se Blocks creation of new managers instead use static method getInstance
*/
public function SingletonExample(se:SingletonEnforcer)
{
}
}
}
internal class SingletonEnforcer {public function SingletonEnforcer(){}}
using this single shared instance from any other class would look something like this:
private var singletonInstance:SingletonExample = SingletonExample.getInstance();
ShaunHusain's theory of using a Singleton was the perfect solution I needed. However, his code gave me a bizarre 1061 error and my format and code appeared to be error free. Regardless, I looked up another way to use a Singleton as follows that worked perfectly for me. Honestly, Shaun's code should work for anyone and I have no idea why it wasn't. I am perfectly willing to admit that it was probably a typo on my end that I just did not see.
I ended up embedding the Set and Get within the Singletons class and used it as an intermediary to hold the information I needed. It worked perfectly.
package chart {
import chart.*;
//
public class StaticInstance {
private static var instance:StaticInstance;
private static var allowInstantiation:Boolean;
private var language:String;
public static function getInstance():StaticInstance {
if (instance == null) {
allowInstantiation = true;
instance = new StaticInstance();
allowInstantiation = false;
}
return instance;
}
public function StaticInstance():void {
if (!allowInstantiation) {
throw new Error("Error: Instantiation failed: Use StaticInsance.getInstance() instead of new.");
}
}
public function setLanguage(_language:String):void{
language = _language;
trace("language set = " + language);
}
public function getLanguage():String{
return language;
}
}
}
This code allowed me to hold the data and call upon it again from two different classes. It's a very hack job instead of just being able to pass on the variable from function to function, but in my case we didn't create this file, we are modifying it and attempting to do things beyond the original scope of the project.
Thanks again for your help Shaun! I hope this helps other people!
I currently have a mobile application on the playbook that has the following class:
[Bindable]
public class Foo
{
public var myString:String;
public var myList:ArrayCollection;
public function Foo() {}
}
I also have persistNavigatorState="true" in my ViewNavigatorApplication.
Suppose in my first view I have the following in my creationComplete="init()" call:
private function init():void {
var s:String = "test_string";
var a:ArrayCollection = new ArrayCollection();
a.addItem("test1");
a.addItem("test2");
a.addItem("test3");
data.foo = new Foo();
data.foo.myString = s;
data.foo.myList = a;
trace(data.foo.myString);
trace(data.foo.myList[0]);
trace(data.foo.myList[1]);
trace(data.foo.myList[2]);
}
When executed, everything works fine in my app. However, since I want the sessions to persist in case the user accidentally closes the app, when he re-opens it the data should still be there.
Instead, when I close and re-open my app only the myString property persists (ie traces "test_string", as intended), however the ArrayCollection isn't copied.
I've tried the following with ObjectUtil.clone() and ObjectUtil.copy():
data.foo.myString = ObjectUtil.copy(s) as String;
data.foo.myList = ObjectUtil.copy(a) as ArrayCollection;
and I've also tried:
var f:Foo = new Foo();
f.myString = s;
f.myList = a;
data.foo = ObjectUtil.copy(f) as Foo;
trace(data.foo.myString);
trace(data.foo.myList[0]);
but this only throws me a
TypeError: Error #1009: Cannot access a property or method of a null object reference.
Any ideas on how to persist ArrayCollections and Foo class in a mobile application?
I'm not 100% sure, but I was wondering about this type of problem while working on a mobile app recently.
I believe your problem might be happening b/c your are setting the data manually on the View, instead of passing it into the View with the ViewNavigator.pushView() method.
I just browsed through the source, and it looks like setting the data directly on the View will bypass ViewNavigator's data persistence. Though with that said, I'm not sure why it would even remember the value for that String :)
I would try to do the following:
don't set the View's data property from inside the view, as you are doing now in the creationComplete handler
if possible, use the "firstView" property of ViewNavigatorApplication in mxml
if possible, initialize the "firstViewData" property in mxml (may not be possible)
if you can't do the two above, in your application's startup code call navigator.pushView(View_Class_Name, foo) to pass in the data.