protected override void OnPropertyChanged(LimeProperty prop, PropertyChangedEventArgs e) { if (string.IsNullOrEmpty(e.PropertyName) || e.PropertyName == "Content") { LimeMsg.Debug("LimeListView OnPropertyChanged: {0} : {1} : {2}", prop, prop?.Ident, e?.PropertyName); int idx = 0; // Bellow we try to re-use the existing controls to avoid rendering overhead if (prop != null) { LimePropertyCollection collec; if (typeof(LimePropertyCollection).IsAssignableFrom(prop.Type)) { collec = (LimePropertyCollection)prop.Content; } else { collec = new LimePropertyCollection(null, prop); } for (int i = 0; i < collec.Count; i++) { var sprop = collec[i]; LimeControl wxctrl = null; var type = LimeControlSelector(sprop); if (type == null) { continue; } if (idx < wxMain.Items.Count) { var wxitem = (LimeControl)wxMain.Items[idx]; var propitem = (LimeProperty)wxitem.DataContext; if (type == wxitem.GetType()) { LimeMsg.Debug("LimeListView OnPropertyChanged: recycle {0} : {1} --> {2}", idx, propitem, sprop); wxitem.DataContext = sprop; wxitem.Visibility = sprop?.Visible == true ? Visibility.Visible : Visibility.Collapsed; } else { LimeMsg.Debug("LimeListView OnPropertyChanged: replaced {0} : {1} --> {2}", idx, propitem, sprop); wxMain.Items[idx] = wxctrl = (LimeControl)Activator.CreateInstance(type); } } else { LimeMsg.Debug("LimeListView OnPropertyChanged: new {0} : {1}", idx, sprop); wxMain.Items.Add(wxctrl = (LimeControl)Activator.CreateInstance(type)); } if (wxctrl != null) { wxctrl.IsTabStop = false; wxctrl.Level = Level > 0.11 ? Level - 0.1 : Level; wxctrl.ReadOnly = ReadOnly; wxctrl.HeaderEnabled = HeaderEnabled; wxctrl.ValidateOnChange = ValidateOnChange; wxctrl.DataContext = sprop; } idx++; } } // Hide remaining items from previous bindings for (; idx < wxMain.Items.Count; idx++) { var wxitem = (LimeControl)wxMain.Items[idx]; wxitem.DataContext = null; wxitem.Visibility = Visibility.Collapsed; } } }
private static void OnBoundDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var wxThis = d as LimeControl; var isLimeControl = wxThis != null && wxThis.GetType() == typeof(LimeControl); //LimeMsg.Debug("LimeControl OnBoundDataContextChanged: {0}", e.NewValue); if (e.OldValue is LimeProperty old) { old.PropertyChangedWeak -= wxThis.TriggerDataContextChanged; } var prop = e.NewValue as LimeProperty; var content = prop != null ? prop.Content : e.NewValue; // Unpack from Matryoshka if (content is IMatryoshka matr) { // Find the most inner matryoshka object while (matr.Content is IMatryoshka sub) { matr = sub; } content = matr.Content; // Repack into a LimeProperty if (prop != null) { prop = new LimeProperty(null, matr, "Content", prop); } else { prop = new LimeProperty(null, matr, "Content"); } } // Encapsulate into LimeProperty if (prop == null && content != null) { prop = new LimeProperty(null, content); e = new DependencyPropertyChangedEventArgs(e.Property, e.OldValue, prop); } // Select the right LimeControl sub-class depending on the Type of the LimeProperty LimeControl wxbind = wxThis; if (isLimeControl) { #if DEBUG wxThis.ADebug = prop != null?string.Format("{1} [{0}] (base)", prop.Type, prop.Ident ?? prop.Name) : "null (base)"; #endif // Type dispatcher var type = LimeControlSelector(prop); LimeControl wxobj = null; if (type == null) { // do nothing } else if (type != wxThis.Content?.GetType()) { wxobj = (LimeControl)Activator.CreateInstance(type); wxobj.Base = wxThis; } else { wxobj = (LimeControl)wxThis.Content; } wxThis.Content = wxbind = wxobj; #if DEBUG if (wxobj != null) { wxobj.ADebug = prop != null?string.Format("{1} [{0}] (content)", prop.Type, prop.Ident ?? prop.Name) : "null (content)"; } #endif } // Bind property to this Control (or content) if (prop != null) { prop.PropertyChangedWeak += wxbind.TriggerDataContextChanged; } if (wxThis != null && wxThis.Content is FrameworkElement wxcont) { wxcont.DataContext = prop; } // Event trigger wxbind?.OnBoundDataContextChanged(e); if (!isLimeControl && wxbind != null) { // Trigger Binding initialization wxbind.TriggerDataContextChanged(prop, new PropertyChangedEventArgs(null)); } }