Xamarin视图不令人耳目一新

时间:2017-11-17 20:51:04

标签: c# xamarin.forms

我的Xamarin XAML页面及其viewmodel存在一些问题。

我已经用一堆方法编写了代码,这些方法是通过XAML的命令执行的。

在功能上它的所有工作都按照需要。但是,方法执行完毕后视图不会刷新。因此,尽管插入内容并从我的可观察集合中删除内容(通过API调用更新),并且有一个notifypropertychanged事件,页面也不会重新加载。

有什么想法吗?

ViewModel (省略了一些属性以符合帖子的字符数限制)

namespace TechsportiseApp.ViewModels
{
    public class ResultsProcessViewModel : INotifyPropertyChanged
    {

        public ICommand AddTimingCommand { get; set; }
        public ICommand AddScanCommand { get; set; }
        public ICommand DeleteTimingCommand { get; set; }
        public ICommand DeleteScanCommand { get; set; }
        public ICommand PublishCommand { get; set; }
        public ICommand LoadResultsCommand { get; set; }
        public ICommand MissingFinisherCommand { get; set; }
        public ICommand MissingTimingCommand { get; set; }

        public int RaceId { get; set; }
        public DateTime RaceDate { get; set; }

        //public ResultsViewModel(Race race)
        public ResultsProcessViewModel(Race race)
        {
            AddTimingCommand = new Command(AddTiming);
            AddScanCommand = new Command(AddScan);
            DeleteTimingCommand = new Command<int>(DeleteTiming);
            DeleteScanCommand = new Command<int>(DeleteScan);
            PublishCommand = new Command<string>(Publish);
            LoadResultsCommand = new Command<int>(LoadResults);
            MissingFinisherCommand = new Command(MissingFinisher);
            MissingTimingCommand = new Command(MissingTiming);

            Invalid = false;

            AddTimingVisibility = false;
            AddScanVisibility = false;
            AddVisibility = true;
            PublishProvisionalVisibility = false;
            PublishFinalVisibility = false;
            IsBusy = false;
            RaceId = race.Id;
            RaceDate = race.RaceDate;
            RaceStartTime = Convert.ToDateTime(race.RaceStartTime);
            Scans = ScansAPI.GetScans(RaceId);
            Timings = TimingsAPI.GetTimings(RaceId);
            Entries = EntriesAPI.GetEntries(RaceId);
            LoadResults(RaceId);
        }



        ObservableCollection<Result> _results;
        public ObservableCollection<Result> Results
        {
            get
            {
                return _results;
            }
            set
            {
                if (_results != value)
                {
                    _results = value;
                    OnPropertyChanged("Results");
                }
            }
        }

        ObservableCollection<Scan> _scans;
        public ObservableCollection<Scan> Scans
        {
            get
            {
                return _scans;
            }
            set
            {
                if (_scans != value)
                {
                    _scans = value;
                    OnPropertyChanged("Scans");
                }
            }
        }

        ObservableCollection<Timing> _timings;
        public ObservableCollection<Timing> Timings
        {
            get
            {
                return _timings;
            }
            set
            {
                if (_timings != value)
                {
                    _timings = value;
                    OnPropertyChanged("Timings");
                }
            }

        }

        ObservableCollection<RaceEntry> _entries;
        public ObservableCollection<RaceEntry> Entries
        {
            get
            {
                return _entries;
            }
            set
            {
                if (_entries != value)
                {
                    _entries = value;
                    OnPropertyChanged("Entries");
                }
            }
        }



        ObservableCollection<Race> _races;
        public ObservableCollection<Race> Races
        {
            get
            {
                try
                {
                    var racelist = RacesAPI.GetRaces();
                    var sortedracelist = new ObservableCollection<Race>(racelist.OrderBy(c => c.Name));
                    var racecount = racelist.Count();
                    if (racecount == 0)
                    {
                        RaceCountZero = true;
                    }
                    else
                    {
                        RaceCountZero = false;
                    }

                    return racelist;
                }
                catch
                {
                    Invalid = true;
                    ValidationError = "Error getting Race List. No internet connection available.";
                }


                return _races;


            }
            set
            {
                if (_races != value)
                {
                    _races = value;
                    OnPropertyChanged("Races");
                }
            }
        }

        string _aboveBelow;
        public string AboveBelow
        {
            get { return _aboveBelow; }
            set
            {
                if (_aboveBelow == value)
                    return;

                _aboveBelow = value;
                OnPropertyChanged("AboveBelow");
            }
        }

        string _aboveBelowPosition;
        public string AboveBelowPosition
        {
            get { return _aboveBelowPosition; }
            set
            {
                if (_aboveBelowPosition == value)
                    return;

                _aboveBelowPosition = value;
                OnPropertyChanged("AboveBelowPosition");
            }
        }

        string _addHH;
        public string AddHH
        {
            get { return _addHH; }
            set
            {
                if (_addHH == value)
                    return;

                _addHH = value;
                OnPropertyChanged("AddHH");
            }
        }

        string _addMM;
        public string AddMM
        {
            get { return _addMM; }
            set
            {
                if (_addMM == value)
                    return;

                _addMM = value;
                OnPropertyChanged("AddMM");
            }
        }

        string _addSS;
        public string AddSS
        {
            get { return _addSS; }
            set
            {
                if (_addSS == value)
                    return;

                _addSS = value;
                OnPropertyChanged("AddSS");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            var changed = PropertyChanged;
            if (changed != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        void AddTiming()
        {
            AddScanVisibility = false;
            AddTimingVisibility = !AddTimingVisibility;
        }

        void AddScan()
        {
            AddScanVisibility = !AddScanVisibility;
            AddTimingVisibility = false;
        }

        void MissingFinisher()
        {
            //Do stuff when deleting a scan. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection
            Task.Run(() =>
            {
                try
                {
                    var scancount = Scans.Count();

                    Device.BeginInvokeOnMainThread(() => IsBusy = true);
                    var IsThereConnection = GlobalFunctions.CheckForInternetConnection();

                    if (IsThereConnection == false)
                        throw new Exception("You cannot add a scan whilst you are offline");
                    else if (string.IsNullOrEmpty(MissingBib))
                        throw new Exception("You must enter a bib number");                  
                    else if (string.IsNullOrEmpty(AboveBelow))
                        throw new Exception("You must choose if you are adding the bib above or below");
                    else if (string.IsNullOrEmpty(AboveBelowPosition))
                        throw new Exception("You must enter the position you are inserting " + AboveBelow);
                    else if (Convert.ToInt32(AboveBelowPosition) > scancount)
                        throw new Exception("The position you have chosen to insert above or below does not exist. Please enter a valid value");
                    else if (Convert.ToInt32(AboveBelowPosition) < 1)
                        throw new Exception("The position you have chosen to insert above or below does not exist. Please enter a valid value");
                    //We are good to go
                    else
                    {
                        var InsertedSequence = new int();
                        var abovebelow = Scans.SingleOrDefault(i => i.Position == Convert.ToInt32(AboveBelowPosition));
                        var abposition = Convert.ToInt32(AboveBelowPosition);
                        if (AboveBelow == "Above")
                        {
                            InsertedSequence = abovebelow.Sequence + 5;
                        }
                        else if (AboveBelow == "Below")
                        {
                            InsertedSequence = abovebelow.Sequence - 5;
                        }
                        else
                        {
                            return;
                        }
                        //Need to add resequencing and reallocation of position numbers
                        var scan = new ScanPost
                        {
                            RaceId = RaceId,
                            BibNumber = MissingBib,
                            Sequence = InsertedSequence,
                            Position = abposition,
                            Reorder = true,
                            Status = 0
                        };

                        var createscan = ScansAPI.CreateScan(scan);

                        if (createscan.Code != "Created")
                            throw new Exception("Error creating scan");
                    }
                }
                catch (Exception ex)
                {
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        ValidationError = ex.Message;
                        Invalid = true;
                    });

                    return;
                }
                finally
                {
                    Device.BeginInvokeOnMainThread(() => IsBusy = false);
                    LoadResults(RaceId);
                    OnPropertyChanged("Results");
                }
            });
        }

        void MissingTiming()
        {
            Task.Run(() =>
            {
                try
                {
                    var timingcount = Timings.Count();

                    Device.BeginInvokeOnMainThread(() => IsBusy = true);
                    var IsThereConnection = GlobalFunctions.CheckForInternetConnection();

                    if (IsThereConnection == false)
                        throw new Exception("You cannot add a timing whilst you are offline");
                    //We are good to go
                    else
                    {
                        if (AddHH == "") { AddHH = "0"; }
                        if (AddMM == "") { AddMM = "0"; }
                        if (AddSS == "") { AddSS = "0"; }

                        var ManualEndTime = RaceStartTime.AddHours(Convert.ToDouble(AddHH))
                                                        .AddMinutes(Convert.ToDouble(AddMM))
                                                        .AddSeconds(Convert.ToDouble(AddSS));

                        var timing = new TimingPost
                           {
                               RaceId = RaceId,
                               StartTime = RaceStartTime,
                               EndTime = ManualEndTime,
                               Reorder = true,
                               Position = 0,
                               Status = 0
                           };

                        var createtiming = TimingsAPI.CreateTiming(timing);

                        if (createtiming.Code != "Created")
                            throw new Exception("Error creating timing");
                    }
                }
                catch (Exception ex)
                {
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        ValidationError = ex.Message;
                        Invalid = true;
                    });

                    return;
                }
                finally
                {
                    Device.BeginInvokeOnMainThread(() => IsBusy = false);
                    Device.BeginInvokeOnMainThread(() => LoadResults(RaceId));
                    Device.BeginInvokeOnMainThread(() => OnPropertyChanged("Results"));
                }
            });

        }

        void DeleteTiming(int timingid)
        {
            //Do stuff when deleting a timing. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection
            Task.Run(() =>
            {
                try
                {

                    Device.BeginInvokeOnMainThread(() => IsBusy = true);
                    var IsThereConnection = GlobalFunctions.CheckForInternetConnection();

                    if (IsThereConnection == false)
                        throw new Exception("You cannot delete a timing whilst you are offline");

                    //We are good to go
                    else
                    {
                        var deletetiming = TimingsAPI.DeleteTiming(timingid);

                        if (deletetiming.Code != "NoContent")
                            throw new Exception("Error deleting timing");
                    }
                }
                catch (Exception ex)
                {

                    Device.BeginInvokeOnMainThread(() =>
                    {
                        ValidationError = ex.Message;
                        Invalid = true;

                    });

                    return;
                }
                finally
                {
                    Device.BeginInvokeOnMainThread(() => IsBusy = false);
                    LoadResults(RaceId);
                    OnPropertyChanged("Timings");
                    Device.BeginInvokeOnMainThread(() => LoadResults(RaceId));
                    Device.BeginInvokeOnMainThread(() => OnPropertyChanged("Timings"));
                }
            });
        }

        void DeleteScan(int scanid)
        {

            //Do stuff when deleting a scan. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection
            Task.Run(() =>
            {
                try
                {

                    Device.BeginInvokeOnMainThread(() => IsBusy = true);
                    var IsThereConnection = GlobalFunctions.CheckForInternetConnection();

                    if (IsThereConnection == false)
                        throw new Exception("You cannot delete a scan whilst you are offline");

                    //We are good to go
                    else
                    {
                        var deletetiming = TimingsAPI.DeleteTiming(scanid);

                        if (deletetiming.Code != "NoContent")
                            throw new Exception("Error deleting scan");
                    }
                }
                catch (Exception ex)
                {

                    Device.BeginInvokeOnMainThread(() =>
                    {
                        ValidationError = ex.Message;
                        Invalid = true;

                    });

                    return;
                }
                finally
                {
                    Device.BeginInvokeOnMainThread(() => IsBusy = false);
                    LoadResults(RaceId);
                    OnPropertyChanged("Results");
                }
            });


        }

        void Publish(string status)
        {

            Task.Run(() =>
            {
                try
                {
                    var publish = new Publish();
                    publish.RaceId = RaceId;
                    publish.ResultStatus = status;

                    Device.BeginInvokeOnMainThread(() => IsBusy = true);
                    var IsThereConnection = GlobalFunctions.CheckForInternetConnection();

                    if (IsThereConnection == false)
                        throw new Exception("You cannot publish results whilst you are offline");

                    //We are good to go
                    else
                    {
                        var publishrace = RacesAPI.PublishRace(publish);

                        if (publishrace.Code != "NoContent")
                            throw new Exception("Error publishing race");
                    }
                }
                catch (Exception ex)
                {

                    Device.BeginInvokeOnMainThread(() =>
                    {
                        ValidationError = ex.Message;
                        Invalid = true;

                    });

                    return;
                }
                finally
                {
                    Device.BeginInvokeOnMainThread(() => IsBusy = false);
                    LoadResults(RaceId);
                    OnPropertyChanged("Results");
                }
            });


        }



        void LoadResults(int raceid)
        {


            var results = new ObservableCollection<Result>();



            //Start with the timings
            foreach (Timing timing in Timings)
            {
                var result = new Result();

                //Basic details
                result.RaceId = RaceId;
                result.RaceDate = RaceDate;
                result.Status = "Processing";

                //Timing Data
                result.TimingId = timing.Id;
                result.TimingPosition = timing.Position;
                result.TimingStatus = timing.Status;
                result.StartTime = timing.StartTime;
                result.EndTime = timing.EndTime;

                var elapsed = result.EndTime - result.StartTime;

                string elapsedhours = elapsed.Hours.ToString();
                string elapsedminutes = elapsed.Minutes.ToString();
                string elapsedseconds = elapsed.Seconds.ToString();
                string elapsedmillis;
                if (elapsed.Milliseconds.ToString().Length > 2)
                {
                    elapsedmillis = elapsed.Milliseconds.ToString().Substring(0, 2);
                }
                else
                {
                    elapsedmillis = elapsed.Milliseconds.ToString();
                }




                if (elapsedhours.Length == 1) { elapsedhours = "0" + elapsedhours; }
                if (elapsedminutes.Length == 1) { elapsedminutes = "0" + elapsedminutes; }
                if (elapsedseconds.Length == 1) { elapsedseconds = "0" + elapsedseconds; }
                if (elapsedmillis.Length == 1) { elapsedmillis = "0" + elapsedmillis; }



                if((elapsedhours == "00"))
                {
                    result.Elapsed = elapsedminutes + ":" + elapsedseconds + "." + elapsedmillis;
                }
                else 
                {
                    result.Elapsed = elapsedhours + ":" + elapsedminutes + ":" + elapsedseconds + "." + elapsedmillis;
                }


                results.Add(result);
            }

            //Add in the scans
            foreach (Result result1 in results)
            {
                var scan = Scans.FirstOrDefault(p => p.Position == result1.TimingPosition);
                if (scan != null)
                {
                    result1.ScanId = scan.Id;
                    result1.ScanPosition = scan.Position;
                    result1.ScanStatus = scan.Status;
                    result1.ScanBibNumber = scan.BibNumber;
                }
                else
                {
                    result1.ScanId = 0;
                    result1.ScanPosition = 0;
                    result1.ScanStatus = 99;
                    result1.ScanBibNumber = "UNKNOWN";
                }
            }

            //Add any scans which there are no times for (Higher than count)
            var timingscount = Timings.Count();
            var notimescans = new ObservableCollection<Scan>();
            foreach (Scan scan in Scans)
            {
                if (scan.Position > timingscount)
                {
                    var newresult = new Result();

                    newresult.RaceId = RaceId;
                    newresult.RaceDate = RaceDate;
                    newresult.Status = "Processing";
                    newresult.ScanId = scan.Id;
                    newresult.ScanPosition = scan.Position;
                    newresult.ScanStatus = scan.Status;
                    newresult.ScanBibNumber = scan.BibNumber;

                    newresult.TimingId = 0;
                    newresult.TimingPosition = 99999;
                    newresult.TimingStatus = 99;
                    newresult.StartTime = RaceStartTime;
                    newresult.EndTime = RaceStartTime;

                    var elapsed = newresult.EndTime - newresult.StartTime;

                    string elapsedhours = elapsed.Hours.ToString();
                    string elapsedminutes = elapsed.Minutes.ToString();
                    string elapsedseconds = elapsed.Seconds.ToString();
                    string elapsedmillis = elapsed.Milliseconds.ToString();

                    if (elapsedhours.Length == 1) { elapsedhours = "0" + elapsedhours; }
                    if (elapsedminutes.Length == 1) { elapsedminutes = "0" + elapsedminutes; }
                    if (elapsedseconds.Length == 1) { elapsedseconds = "0" + elapsedseconds; }
                    if (elapsedmillis.Length == 1) { elapsedmillis = "0" + elapsedmillis; }

                    if ((elapsedhours == "00"))
                    {
                        newresult.Elapsed = elapsedminutes + ":" + elapsedseconds + "." + elapsedmillis;
                    }
                    else
                    {
                        newresult.Elapsed = elapsedhours + ":" + elapsedminutes + ":" + elapsedseconds + "." + elapsedmillis;
                    }


                    results.Add(newresult);
                }
            }

            //Then add in the entries
            foreach (Result result2 in results)
            {

                var entry = Entries.FirstOrDefault(p => p.BibNumber == result2.ScanBibNumber);
                if (entry != null)
                {
                    result2.EntryId = entry.Id;
                    result2.FirstName = entry.FirstName;
                    result2.LastName = entry.LastName;
                    result2.FormattedName = entry.FirstName + " " + entry.LastName.ToUpper();
                    result2.Gender = entry.Gender;
                    result2.DateOfBirth = entry.DateOfBirth;
                    result2.Club = entry.Club;
                    result2.Team = entry.Team;
                    result2.EntryBibNumber = entry.BibNumber;
                }
                else
                {
                    result2.EntryId = 0;
                    result2.FirstName = "Unknown";
                    result2.LastName = "ATHLETE";
                    result2.Gender = "Unknown";
                    result2.DateOfBirth = DateTime.Now;
                    result2.Club = "";
                    result2.Team = "";
                    result2.EntryBibNumber = "Unknown";
                }

            }
            var sortedresults = new ObservableCollection<Result>(results.OrderBy(c => c.TimingPosition));
            Results = sortedresults;
            OnPropertyChanged("Results");

        }



    }
}

0 个答案:

没有答案