【问题标题】:Function in App.xaml.cs being called twice when the app startsApp.xaml.cs 中的函数在应用启动时被调用两次
【发布时间】:2014-09-16 17:57:59
【问题描述】:

我正在构建一个 Windows 手机应用程序,我遇到了这个问题:我在 App.xaml.cs 文件中有一个 FirstRun() 函数,用于检查应用程序是否首次运行。我收到了 2 个消息框,每次都显示给我(第一次运行而不是第一次运行)。问题是,当我第一次运行应用程序时,我收到消息“首次运行”,但之后,没有继续,我收到另一条消息“不是第一次运行”,程序没有继续执行需要的功能第一次运行时执行。什么会导致对 IsFirstRun() 函数的“双重”调用并返回不同的结果?以下是函数:

 public static bool IsFirstRun()
    {
        if (!settings.Contains(FIRST_RUN_FLAG)) //First time running
        {
            settings.Add(FIRST_RUN_FLAG, false);
            return true;
        }
        return false;   
    }

还有帮助我找到正确页面的 UriMapper:

公共类 FirstRunUriMapper : UriMapperBase { 公共覆盖 Uri MapUri(Uri uri) {

        if (uri.OriginalString == "/LaunchPage.xaml")
        {
            MessageBox.Show("Searching for LaunchPage...");
            if (App.IsFirstRun())
            {
                MessageBox.Show("First run...Should show introductionPage...");
                uri = new Uri("/MainPage.xaml", UriKind.Relative);
            }
            else
            {
                MessageBox.Show("...Should show MainPage...");
                uri = new Uri("/IntroductionPage.xaml", UriKind.Relative);
            }
        }
        return uri;
    }
}

编辑: 按照要求,我为整个班级提供了修改后的 UriMapper,现在可以正常工作,但仍然找不到导致双重 MapUri() 方法调用的原因:

  public class FirstRunUriMapper : UriMapperBase
{

    public override Uri MapUri(Uri uri)
    {

        if (uri.OriginalString == "/LaunchPage.xaml")
        {
            if (App.FirstRun)
            {
                if (App.IsFirstRun())
                {
                    uri = new Uri("/IntroductionPage.xaml", UriKind.Relative);
                }
                else
                {
                    uri = new Uri("/IntroductionPage.xaml", UriKind.Relative);
                    App.FirstRun = false;
                }
            }
            else
            {
                uri = new Uri("/MainPage.xaml", UriKind.Relative);
            }
        }
        return uri;
    }
}

还有App.xaml.cs 类:

公共部分类应用程序:应用程序 {

    private static string FIRST_RUN_FLAG = "FIRST_RUN_FLAG";
    private static IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
    public static bool FirstRun = true;

    /// <summary>
    /// Provides easy access to the root frame of the Phone Application.
    /// </summary>
    /// <returns>The root frame of the Phone Application.</returns>
    public static PhoneApplicationFrame RootFrame { get; private set; }

    /// <summary>
    /// Checks if the app runs for the first time
    /// </summary>
    /// <returns>True if the app runs for the first time, otherwise false.</returns>
    public static bool IsFirstRun()
    {
        if (!settings.Contains(FIRST_RUN_FLAG)) //First time running
        {
            settings.Add(FIRST_RUN_FLAG, false);
            return true;
        }
        return false;   
    }


    public void loadModel()
    {
        string dataFromAppSettings;
        ContactLensesModel model;

        //Search for the string into the Application Settings
        if (IsolatedStorageSettings.ApplicationSettings.TryGetValue(MainPage.Model.modelKey, out dataFromAppSettings))
        {
            model = JsonConvert.DeserializeObject<ContactLensesModel>(dataFromAppSettings);
            MainPage.Model = model;
        }
        else //The model does not exist
        {
            MainPage.Model = null;

        }
    }

    public void saveModel()
    {
        //Convert to a JSON format
        var modelData = JsonConvert.SerializeObject(MainPage.Model);

        //Save the model to the settings
        IsolatedStorageSettings.ApplicationSettings[MainPage.Model.modelKey] = modelData;
        IsolatedStorageSettings.ApplicationSettings.Save();
    }


    /// <summary>
    /// Constructor for the Application object.
    /// </summary>
    public App()
    {
        // Global handler for uncaught exceptions.
        UnhandledException += Application_UnhandledException;

        // Standard XAML initialization
        InitializeComponent();

        // Phone-specific initialization
        InitializePhoneApplication();

        // Language display initialization
        InitializeLanguage();

        // Show graphics profiling information while debugging.
        if (Debugger.IsAttached)
        {
            // Display the current frame rate counters.
            Application.Current.Host.Settings.EnableFrameRateCounter = true;

            // Show the areas of the app that are being redrawn in each frame.
            //Application.Current.Host.Settings.EnableRedrawRegions = true;

            // Enable non-production analysis visualization mode,
            // which shows areas of a page that are handed off to GPU with a colored overlay.
            //Application.Current.Host.Settings.EnableCacheVisualization = true;

            // Prevent the screen from turning off while under the debugger by disabling
            // the application's idle detection.
            // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
            // and consume battery power when the user is not using the phone.
            PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
        }

    }

    // Code to execute when the application is launching (eg, from Start)
    // This code will not execute when the application is reactivated
    private void Application_Launching(object sender, LaunchingEventArgs e)
    {
        RootFrame.UriMapper = new FirstRunUriMapper();
        loadModel();
    }



    // Code to execute when the application is activated (brought to foreground)
    // This code will not execute when the application is first launched
    private void Application_Activated(object sender, ActivatedEventArgs e)
    {
        loadModel();
        if (e.IsApplicationInstancePreserved == false)
        {
            RootFrame.UriMapper = new FirstRunUriMapper();

        }
    }

    // Code to execute when the application is deactivated (sent to background)
    // This code will not execute when the application is closing
    private void Application_Deactivated(object sender, DeactivatedEventArgs e)
    {
        saveModel();
    }



    // Code to execute when the application is closing (eg, user hit Back)
    // This code will not execute when the application is deactivated
    private void Application_Closing(object sender, ClosingEventArgs e)
    {
        saveModel();
    }

    // Code to execute if a navigation fails
    private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
    {
        if (Debugger.IsAttached)
        {
            // A navigation has failed; break into the debugger
            Debugger.Break();
        }
    }

    // Code to execute on Unhandled Exceptions
    private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
    {
        if (Debugger.IsAttached)
        {
            // An unhandled exception has occurred; break into the debugger
            Debugger.Break();
        }
    }

    #region Phone application initialization

    // Avoid double-initialization
    private bool phoneApplicationInitialized = false;

    // Do not add any additional code to this method
    private void InitializePhoneApplication()
    {
        if (phoneApplicationInitialized)
            return;

        // Create the frame but don't set it as RootVisual yet; this allows the splash
        // screen to remain active until the application is ready to render.
        RootFrame = new PhoneApplicationFrame();
        RootFrame.Navigated += CompleteInitializePhoneApplication;

        // Handle navigation failures
        RootFrame.NavigationFailed += RootFrame_NavigationFailed;

        // Handle reset requests for clearing the backstack
        RootFrame.Navigated += CheckForResetNavigation;

        // Ensure we don't initialize again
        phoneApplicationInitialized = true;
    }

    // Do not add any additional code to this method
    private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
    {
        // Set the root visual to allow the application to render
        if (RootVisual != RootFrame)
            RootVisual = RootFrame;

        // Remove this handler since it is no longer needed
        RootFrame.Navigated -= CompleteInitializePhoneApplication;
    }

    private void CheckForResetNavigation(object sender, NavigationEventArgs e)
    {
        // If the app has received a 'reset' navigation, then we need to check
        // on the next navigation to see if the page stack should be reset
        if (e.NavigationMode == NavigationMode.Reset)
            RootFrame.Navigated += ClearBackStackAfterReset;
    }

    private void ClearBackStackAfterReset(object sender, NavigationEventArgs e)
    {
        // Unregister the event so it doesn't get called again
        RootFrame.Navigated -= ClearBackStackAfterReset;

        // Only clear the stack for 'new' (forward) and 'refresh' navigations
        if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh)
            return;

        // For UI consistency, clear the entire page stack
        while (RootFrame.RemoveBackEntry() != null)
        {
            ; // do nothing
        }
    }

    #endregion

    // Initialize the app's font and flow direction as defined in its localized resource strings.
    //
    // To ensure that the font of your application is aligned with its supported languages and that the
    // FlowDirection for each of those languages follows its traditional direction, ResourceLanguage
    // and ResourceFlowDirection should be initialized in each resx file to match these values with that
    // file's culture. For example:
    //
    // AppResources.es-ES.resx
    //    ResourceLanguage's value should be "es-ES"
    //    ResourceFlowDirection's value should be "LeftToRight"
    //
    // AppResources.ar-SA.resx
    //     ResourceLanguage's value should be "ar-SA"
    //     ResourceFlowDirection's value should be "RightToLeft"
    //
    // For more info on localizing Windows Phone apps see http://go.microsoft.com/fwlink/?LinkId=262072.
    //
    private void InitializeLanguage()
    {
        try
        {
            // Set the font to match the display language defined by the
            // ResourceLanguage resource string for each supported language.
            //
            // Fall back to the font of the neutral language if the Display
            // language of the phone is not supported.
            //
            // If a compiler error is hit then ResourceLanguage is missing from
            // the resource file.
            RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage);

            // Set the FlowDirection of all elements under the root frame based
            // on the ResourceFlowDirection resource string for each
            // supported language.
            //
            // If a compiler error is hit then ResourceFlowDirection is missing from
            // the resource file.
            FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
            RootFrame.FlowDirection = flow;
        }
        catch
        {
            // If an exception is caught here it is most likely due to either
            // ResourceLangauge not being correctly set to a supported language
            // code or ResourceFlowDirection is set to a value other than LeftToRight
            // or RightToLeft.

            if (Debugger.IsAttached)
            {
                Debugger.Break();
            }

            throw;
        }
    }


}

}

【问题讨论】:

标签: c# windows-phone-8 app.xaml


【解决方案1】:
static bool first = true;

public override Uri MapUri(Uri uri)
{

    if (uri.OriginalString == "/LaunchPage.xaml")
    {
        if (first) MessageBox.Show("Searching for LaunchPage...");

        if (App.IsFirstRun())
        {
            if (first) MessageBox.Show("First run...Should show introductionPage...");
            uri = new Uri("/MainPage.xaml", UriKind.Relative);
        }
        else
        {
            if (first) MessageBox.Show("...Should show MainPage...");
            uri = new Uri("/IntroductionPage.xaml", UriKind.Relative);
        }
        }

        first = false;
    }
    return uri;
}

【讨论】:

  • 这不是问题人... messageBoxes 上不存在问题,而是在应用程序开始时两次调用 MapUri 方法的事实...
  • 但是你不能改变它,除非它是从你自己的代码中调用的。
【解决方案2】:

看看this SO question的例子

您是否尝试过连接 RootFrame.UriMapper 而不是覆盖?

private void Application_Launching(object sender, LaunchingEventArgs e)
{
     RootFrame.UriMapper = new YourUriMapper();
}

【讨论】:

  • 是的,我完全按照这个问题的步骤...问题是MapUri() 方法被调用了两次并导致我出现问题...你知道为什么这个函数被调用两次?我已经搜索了所有内容,但仍然找不到答案...感谢您的帮助!
  • 在示例代码中没有看到静态方法。请提供与示例中一样多的代码,包括您对隔离存储的访问权限以及来自 app.xaml 的应用程序事件,以便我可以看到您的偏差的哪一部分导致了您的问题。如果我能在此期间重现,我会看到自己。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 2018-05-02
  • 2017-06-16
  • 2020-05-03
  • 2013-07-02
相关资源
最近更新 更多