Question

As per MSDN guidelines we need to put all the app's settings into the SettingsPane and then the app should update all pages when the settings is applied.

In my app I need to have a reset option which brings the app to the default settings. There are 2 pages, Calendar.xaml and HistoryStatistics.xaml that i need to update when the reset button is pressed. All the data of the app is put in a singleton class called CycleManager. I have used a SettingsFlyout control from the Callisto Toolkit.

App.Xaml

Registered the settings in the App.xaml

SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested;

and in OnCommandsRequested function, created the reset handler

        var reset = new SettingsCommand("reset", "Reset", (handler) =>
        {
            var settings = new SettingsFlyout();
            settings.Content = new ResetUserControl();
            settings.HeaderBrush = new SolidColorBrush(_background);
            settings.Background = new SolidColorBrush(_background);
            settings.HeaderText = "Reset";
            settings.IsOpen = true;
        });

        args.Request.ApplicationCommands.Add(reset);

CycleManager.cs

In the CycleManager class, there is a m_Reset variable,its setter and getter and an event handler called ResetClicked

    public event EventHandler ResetClicked;

    public bool Reset
    {
        get
        {
            return m_reset;
        }
        set
        {
            m_reset = value;
            if (ResetClicked != null)
                ResetClicked(this, EventArgs.Empty);
        }
    }

Next is the part where i have associated this handler in my first class calendar.xaml

Calendar.xaml

In the constructor of the class I declare the event handler

CycleManager pCycMan = CycleManager.Instance;
pCycMan.ResetClicked += this.ResetClicked;

followed by the definition of the event handler

    private async void ResetClicked(object sender, EventArgs e)
    {
        CycleManager pCycMan = CycleManager.Instance;
        if (pCycMan.Reset == true)
        {
            try
            {                   
                await Windows.Storage.ApplicationData.Current.ClearAsync(Windows.Storage.ApplicationDataLocality.Local);
                pCycMan.InitializeValues();
            }
            catch (Exception)
            {
            }
        }

        CreateCalendar();// UI is loaded
    }  

In the constructor of the HistoryStatistics.xaml I have done the same thing as above

HistoryStatistics.xaml

public HistoryStatistics()
    {
        CycleManager pCycMan = CycleManager.Instance;
        pCycMan.ResetClicked += this.ResetClicked;
    }

and defined

    private void ResetClicked(object sender, EventArgs e)
    {
        CycleManager pCycMan = CycleManager.Instance;
        if (pCycMan.Reset == true)
        {
            await Windows.Storage.ApplicationData.Current.ClearAsync(Windows.Storage.ApplicationDataLocality.Local);
            pCycMan.InitializeValues();
            LoadListView();// loads the UI
            DisplayStatistics();//loads the UI for the page
        }
    } 

Now the problem

  1. Is this the right approach?

  2. When Reset is pressed in the first from the second page(HistoryStatistcs), the reset clicked function declared in the first page(Calendar.xaml.cs) is called first and then the one in HistoryStatistics. And both gets executed async! :( Is this a right behaviour?

This question is quite long. Hope everybody understood the scenario and question.

Was it helpful?

Solution

There is nothing wrong with the behaviour you outlined. Two pages subscribe to an event and event uses multi cast delegate which means they will both get fired.

I think you need a simpler behaviour here. Each xaml page should subscribe to that event on OnNavigatedTo and should unsubscribe in OnNavigatedFrom.

That way only one of the two actually executes the cleanup.

OTHER TIPS

The complexity/confusion is likely coming because of not using the MVVM (model, view, and view model) separation. you may want to read about this. keeping the separation helps. Below are few pointers on this. but not necessarily a full design for your app.

in this example: CycleManager.Instance is kind of serving the model (the data). You may want to rename ResetClicked to SettingChanged and think of the event as notification for clients that one or more settings properties exposed has changed. It should also expose ResetSettings() method that can be called by ResetUserControl.

// model for the settings
class SettingsManager
{
    public event EventHandler SettingsChanged;

    public async void ResetSettings()
    {
        await Windows.Storage.ApplicationData.Current.ClearAsync
              (Windows.Storage.ApplicationDataLocality.Local);
        // initialize all values to default values;
        this._intializeValues();
        if (this.SettingsChanged != null)
            this.SettingsChanged(this, EventArgs.Empty);
    }
}

HistoryStatistics and Calendar class should have view model that should listen for SettingsChanged event and update the properties exposed. Each page view (xaml) binds to the properties exposed by the respective view model. This will require some refactoring of current code.

Without that, ResetClick eventhandlers can be changed to SettingChanged event handlers and take required action. They need not call setting mgr to initialize values.

class HistoryStatistics
{
    private void SettingsChanged(object sender, EventArgs e)
    {
        SettingsManager settingsManager = SettingsManager.Instance;
        LoadListView();// loads the UI
        DisplayStatistics();//loads the UI for the page
    } 
}

HTH.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top