更改集合,CollectionChanged始终为null

时间:2015-01-09 22:50:57

标签: c# wpf data-binding

我正试图解决这个问题。

我正在为另一组数据交换一个集合中的一组数据。我显示数据的UI显示控件加载时的第一个设置,但是当我更改集合内容时不会更改为新的数据集。

我期望NotifyCollectionChanged方法中的CollectionChanged有订阅,但事实并非如此。

StationName在加载时显示在我的UI上,但在重新加载时不会更改。 StationListOfMovements在加载时显示在我的UI上,但在重新加载时不会更改。

我可以在代码中更改现有集合中的各个项目。我在哪里错了?

显示数据的控件

public partial class CisArrivalsPanel : UserControl
    {
        private ApiDataArrivalsDepartures _theArrivalsDepartures;

        public CisArrivalsPanel()
        {
            InitializeComponent();

            _theArrivalsDepartures = new ApiDataArrivalsDepartures();

            _theArrivalsDepartures = MakeQuery.LiveTrainArrivals("London Kings Cross"); //load the first set of data into the collection

            this.DataContext = _theArrivalsDepartures;

            ListBoxArr.ItemsSource = _theArrivalsDepartures.StationMovementList;            
        }


        //this invokes the data collection reload as a test
        private void StationHeader_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            Reload();

            Debug.WriteLine(_theArrivalsDepartures.StationName);
            foreach (var a in _theArrivalsDepartures.StationMovementList)
            {
                Debug.WriteLine(a.OriginName);
                Debug.WriteLine(a.BestArrivalEstimateMins);
            }
        }

        //here I am swapping out the collection contents
        void Reload()
        {
            _theArrivalsDepartures = MakeQuery.LiveTrainArrivals("London Paddington"); //load the second set of data into the collection

        }
    }

该集合

public class ApiDataArrivalsDepartures : INotifyPropertyChanged
    {
        private string _stationName;
        [JsonProperty(PropertyName = "station_name")]
        public string StationName {
            get
            {
                return _stationName;
            }
            set
            {
                _stationName = value;
                NotifyPropertyChanged("StationName");
            } 
        }

        private DateTime _requestTime;
        [JsonProperty(PropertyName = "request_time")]
        public DateTime RequestTime {
            get
            {
                return _requestTime;
            }
            set
            {
                _requestTime = value;
                NotifyPropertyChanged("RequestTime");
            } 
        }

        private string _stationCode;
        [JsonProperty(PropertyName = "station_code")]
        public string StationCode {
            get
            {
                return _stationCode;
            }
            set
            {
                _stationCode = value;
                NotifyPropertyChanged("StationCode");
            } 
        }

        private ObservableCollection<StationListOfMovements> _stationMovementList;

        public ObservableCollection<StationListOfMovements> StationMovementList
        {
            get
            {
                return _stationMovementList;
            }
            set
            {
                _stationMovementList = value;
                NotifyCollectionChanged("StationMovementList");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        private void NotifyCollectionChanged(string property)
        {
            if (CollectionChanged != null)
            {
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset,property));    
            }            
        }
    }


    public class StationListOfMovements : INotifyPropertyChanged
    {

        private string _mode;
        [JsonProperty(PropertyName = "mode")]
        public string Mode
        {
            get
            {
                return _mode;
            }
            set
            {
                _mode = value;
                NotifyPropertyChanged("Mode");
            }
        }


        private string _service;
        [JsonProperty(PropertyName = "service")]
        public string Service {
            get
            {
                return _service;
            }
            set
            {
                _service = value;
                NotifyPropertyChanged("Service");
            } 
        }

        private string _trainUid;
        [JsonProperty(PropertyName = "train_uid")]
        public string TrainUid {
            get
            {
                return _trainUid;
            }
            set
            {
                _trainUid = value;
                NotifyPropertyChanged("TrainUid");
            } 
        }

        private string _originName;
        [JsonProperty(PropertyName = "origin_name")]
        public string OriginName {
            get
            {
                return _originName;
            }
            set
            {
                _originName = value;
                NotifyPropertyChanged("OriginName");
            } 
        }

        private string _destinationName;
        [JsonProperty(PropertyName = "destination_name")]
        public string DestinationName {
            get
            {
                return _destinationName;
            }
            set
            {
                _destinationName = value;
                NotifyPropertyChanged("DestinationName");
            } 
        }

        private string _platform;
        [JsonProperty(PropertyName = "Platform")]
        public string Platform {
            get
            {
                return _platform;
            }
            set
            {
                _platform = value;
                NotifyPropertyChanged("Platform");
            }
        }

   //This is a long boring class, snipped until....

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
    }

UPDATE1:

 /// <summary>
        /// Gets train arrivals for a station
        /// </summary>
        /// <param name="station">The station.</param>
        /// <returns>ApiDataArrivalsDepartures</returns>
        public static ApiDataArrivalsDepartures LiveTrainArrivals(string station)
        {

            string crsCode;
            OvergroundStations.StationDictionary.TryGetValue(station, out crsCode);

            //construct url
            var queryUrl = new Uri(string.Format("{0}{1}{2}{3}",ApiBaseUrl,"train/station/",crsCode,"/live_arrivals"));

            //get json data from API 
            var jsonString = GetDataFromApi(queryUrl);

            //convert to root arrival object
            var arrivals = Deseralise<ApiDataArrivalsDepartures>(jsonString) as ApiDataArrivalsDepartures;

            //convert arrivals board data
            if (arrivals != null)
                arrivals.StationMovementList = Deseralise<ObservableCollection<StationListOfMovements>>(jsonString, "arrivals", "all") as ObservableCollection<StationListOfMovements>;

            return arrivals;
        }

更新2:

static object Deseralise<T>(string jsonString, string token1, string token2)
        {
            var deserializeObject = new object();

            try
            {
                var jsonPass1 = JObject.Parse(jsonString).SelectToken(token1).ToString();

                var jsonPass2 = JObject.Parse(jsonPass1).SelectToken(token2).ToString();

                deserializeObject = JsonConvert.DeserializeObject<T>(jsonPass2);
            }
            catch (Exception ex) { }

            return deserializeObject;
        }

1 个答案:

答案 0 :(得分:0)

ObservableCollection会自动提升CollectionChanged 无需自行提升。它也反对自己,而不是你的VM。

事实上,UI没有理由为它注册(因此是空事件处理程序),因为你的VM甚至没有实现INotifyCollectionChanged(不是你应该的)。

相反,请在您的收藏的NotifyPropertyChanged函数中调用set,然后摆脱CollectionChanged。同时确保每隔时间设置变量,您可以通过属性而不是支持字段进行设置。在字段中设置不会运行属性的set功能,因此NotifyPropertyChanged不会运行。

<强>更新 虽然我的原始观察仍然是值得注意的好事,但我现在注意到实际问题:

    //here I am swapping out the collection contents
    void Reload()
    {
        _theArrivalsDepartures = MakeQuery.LiveTrainArrivals("London Paddington"); //load the second set of data into the collection
    }

ItemsSource的{​​{1}} 设置为旧集合!您所做的就是重新分配您的本地变量,ListBox根本不受影响。这就是你通常直接设置UI属性的原因。相反,您将绑定 ListBox绑定到VM上的属性,然后仅更改该属性,而不是交换整个对象。

同时,请考虑将ItemsSource重新分配给新集合。