简体   繁体   中英

UWP C# How to Use Routine From Different Page

I am intending to write a UWP with navigationview where I use rs485 to communicate to some devices.

I have a DS3231 RTC , which I have made it work previously in earlier app.

My SettingPage is where I configure the time, when I set the time, i ran into error. system.nullreferenceexception: 'object reference not set to an instance of an object.'

My startClock() , readDS3231 and setDS3231 routines are in MainPage.xaml.cs . My datepicker and timepicker routines are in SettingsPage .

Please help to let me know where did I do wrong and how do I correct it. Actually I am quite confused with the page thing. I can't understand it.


SettingsPage.xaml.cs

private void DatePicker_DateChanged(object sender, DatePickerValueChangedEventArgs e)
    {
        DateTimeSettings.SetSystemDateTime(e.NewDate.UtcDateTime);

        mainPage.SetTime_DS3231(e.NewDate.UtcDateTime);
    }

private void TimePicker_TimeChanged(object sender, TimePickerValueChangedEventArgs e)
    {
        var currentDate = DateTime.Now.ToUniversalTime();

        var newDateTime = new DateTime(currentDate.Year,
                                       currentDate.Month,
                                       currentDate.Day,
                                       e.NewTime.Hours,
                                       e.NewTime.Minutes,
                                       e.NewTime.Seconds);

        DateTimeSettings.SetSystemDateTime(newDateTime);

        mainPage.SetTime_DS3231(newDateTime);
    }

private void TimeZoneComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        TimeZoneInfo selectedTimeZone = (TimeZoneInfo)this.TimeZoneComboBox.SelectedItem;
        Zone.Text = selectedTimeZone.ToString();
        TimeZoneInfo.ConvertTime(DateTime.Now, selectedTimeZone);
    }

private void UpdateRTC_Click(object sender, RoutedEventArgs e)
    {
        mainPage.SetTime_DS3231(DateTime.Now);
    }

private void ReadRTC_Click(object sender, RoutedEventArgs e)
    {
        mainPage.GetTime_DS3231();

        ReadSec.Text = mainPage.readSec;
        ReadMin.Text = mainPage.readMin;
        ReadHour.Text = mainPage.readHour;
        ReadDay.Text = mainPage.readDay;
        ReadDate.Text = mainPage.readDate;
        ReadMth.Text = mainPage.readMth;
        ReadYear.Text = mainPage.readYear;
    }

MainPage.xaml.cs

public async void GetTime_DS3231()
    {
        /* DS3231 I2C SLAVE address */
        int SlaveAddress = 0x68;

        try
        {
            // Initialize I2C
            var Settings = new I2cConnectionSettings(SlaveAddress);
            Settings.BusSpeed = I2cBusSpeed.StandardMode;

            if (AQS == null || DIS == null)
            {
                AQS = I2cDevice.GetDeviceSelector("I2C1");
                DIS = await DeviceInformation.FindAllAsync(AQS);
            }

            //rtcError = false;

            using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings))
            {
                byte[] writeBuf = { 0x00 };
                Device.Write(writeBuf);
                byte[] readBuf = new byte[7];
                Device.Read(readBuf);
                byte second = bcdToDec((byte)(readBuf[0] & 0x7f));
                byte minute = bcdToDec(readBuf[1]);
                byte hour = bcdToDec((byte)(readBuf[2] & 0x3f));
                byte dayOfWeek = bcdToDec(readBuf[3]);
                byte dayOfMonth = bcdToDec(readBuf[4]);
                byte month = bcdToDec(readBuf[5]);
                byte year = bcdToDec(readBuf[6]);

                readSec = second.ToString();
                readMin = minute.ToString();
                readHour = hour.ToString();
                readDay = dayOfWeek.ToString();
                readDate = dayOfMonth.ToString();
                readMth = month.ToString();
                readYear = year.ToString();
                
                var currentDate = DateTime.Now.ToUniversalTime();

                var newDateTime = new DateTime(currentDate.Year,
                                       month,
                                       dayOfMonth,
                                       hour,
                                       minute,
                                       second);

                DateTimeSettings.SetSystemDateTime(newDateTime);

            }
        }
        catch (Exception ex)
        {
            MainStatusDisplay.Text = ex.Message;
            //System.Diagnostics.Debug.Write(ex.Message);
        }
    }

    public async void SetTime_DS3231(DateTime dt)
    {
        int SlaveAddress = 0x68;

        try
        {
            // Initialize I2C
            var Settings = new I2cConnectionSettings(SlaveAddress);
            Settings.BusSpeed = I2cBusSpeed.StandardMode;

            if (AQS == null || DIS == null)
            {
                AQS = I2cDevice.GetDeviceSelector("I2C1");
                DIS = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(AQS);
            }

            //rtcError = false;

            using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings))
            {
                byte write_seconds = decToBcd((byte)dt.Second);
                byte write_minutes = decToBcd((byte)dt.Minute);
                byte write_hours = decToBcd((byte)dt.Hour);
                byte write_dayofweek = decToBcd((byte)dt.DayOfWeek);
                byte write_day = decToBcd((byte)dt.Day);
                byte write_month = decToBcd((byte)dt.Month);
                //byte write_year = decToBcd((byte)dt.Year);
                byte write_year = IntToBcd(dt.Year % 100);

                byte[] write_time = { 0x00, write_seconds, write_minutes, write_hours, write_dayofweek, write_day, write_month, write_year };

                Device.Write(write_time);

            }
        }
        catch (Exception ex)
        {
            //rtcError = true;
            MainStatusDisplay.Text = ex.Message;
            //System.Diagnostics.Debug.Write(ex.Message);
        }

    }

在此处输入图像描述

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

You must initialize the member SettingsPage.mainPage with the currently active page instance of MainPage . If you don't use MVVM things become complicated and ugly. For this reason I recommend to introduce a view model which is shared between both views.

Also note that an async method must return Task otherrwise you will experience strange behavior especially when exceptions are thrown by the awaitable method. You also forget to await the asynchronous methods. Consider to follow best practice naming conventions and ad the "Async" suffix to asynchronous methods eg GetTime_DS3231Async :

MainViewModel.cs

class MainViewModel : INotifyPropertyChanged
{
    public async Task GetTimeDs3231Async()
    {
        /* DS3231 I2C SLAVE address */
        int SlaveAddress = 0x68;

        try
        {
            // Initialize I2C
            var Settings = new I2cConnectionSettings(SlaveAddress);
            Settings.BusSpeed = I2cBusSpeed.StandardMode;

            if (AQS == null || DIS == null)
            {
                AQS = I2cDevice.GetDeviceSelector("I2C1");
                DIS = await DeviceInformation.FindAllAsync(AQS);
            }

            //rtcError = false;

            using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings))
            {
                byte[] writeBuf = { 0x00 };
                Device.Write(writeBuf);
                byte[] readBuf = new byte[7];
                Device.Read(readBuf);
                byte second = bcdToDec((byte)(readBuf[0] & 0x7f));
                byte minute = bcdToDec(readBuf[1]);
                byte hour = bcdToDec((byte)(readBuf[2] & 0x3f));
                byte dayOfWeek = bcdToDec(readBuf[3]);
                byte dayOfMonth = bcdToDec(readBuf[4]);
                byte month = bcdToDec(readBuf[5]);
                byte year = bcdToDec(readBuf[6]);

                readSec = second.ToString();
                readMin = minute.ToString();
                readHour = hour.ToString();
                readDay = dayOfWeek.ToString();
                readDate = dayOfMonth.ToString();
                readMth = month.ToString();
                readYear = year.ToString();
                
                var currentDate = DateTime.Now.ToUniversalTime();

                var newDateTime = new DateTime(currentDate.Year,
                                       month,
                                       dayOfMonth,
                                       hour,
                                       minute,
                                       second);

                DateTimeSettings.SetSystemDateTime(newDateTime);

            }
        }
        catch (Exception ex)
        {
            MainStatusDisplay.Text = ex.Message;
            //System.Diagnostics.Debug.Write(ex.Message);
        }
    }

    public async Task SetTimeDs3231Async(DateTime dt)
    {
        int SlaveAddress = 0x68;

        try
        {
            // Initialize I2C
            var Settings = new I2cConnectionSettings(SlaveAddress);
            Settings.BusSpeed = I2cBusSpeed.StandardMode;

            if (AQS == null || DIS == null)
            {
                AQS = I2cDevice.GetDeviceSelector("I2C1");
                DIS = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(AQS);
            }

            //rtcError = false;

            using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings))
            {
                byte write_seconds = decToBcd((byte)dt.Second);
                byte write_minutes = decToBcd((byte)dt.Minute);
                byte write_hours = decToBcd((byte)dt.Hour);
                byte write_dayofweek = decToBcd((byte)dt.DayOfWeek);
                byte write_day = decToBcd((byte)dt.Day);
                byte write_month = decToBcd((byte)dt.Month);
                //byte write_year = decToBcd((byte)dt.Year);
                byte write_year = IntToBcd(dt.Year % 100);

                byte[] write_time = { 0x00, write_seconds, write_minutes, write_hours, write_dayofweek, write_day, write_month, write_year };

                Device.Write(write_time);

            }
        }
        catch (Exception ex)
        {
            //rtcError = true;
            MainStatusDisplay.Text = ex.Message;
            //System.Diagnostics.Debug.Write(ex.Message);
        }    
    }
}

App.xaml

<Application>
  <Application.Resources>
    <MainViewModel x:Key="MainViewModel"/>
  </Application.Resources>
</Application>

MainPage.xam

<Page DataContext="{StaticResource MainViewModel}">

</Page>

SettingsPage.xam

<Page DataContext="{StaticResource MainViewModel}">

</Page>

SettingsPage.xaml.cs

private async void DatePicker_DateChanged(object sender, DatePickerValueChangedEventArgs e)
{
    DateTimeSettings.SetSystemDateTime(e.NewDate.UtcDateTime);

    var viewModel = this.DataContext as MainViewModel;

    // Await the asynchronous method
    await viewModel.SetTimeDs3231Async(e.NewDate.UtcDateTime);
}

At the time you use mainPage.SetTime_DS3231(newDateTime) the variable mainPage has the Value null. Make sure it is correctly initialized. Was it already initialized before that? Then it is probably deleted at some point during your code, maybe when switching pages.

You could try putting this before the mainPage.SetTime_DS3231(newDateTime) :

if(mainPage == null)
    mainPage = new MainPage();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM