/// <summary> /// Creates the child control. /// </summary> /// <returns>The child control or null.</returns> protected virtual IControl CreateChild() { var content = Content; var oldChild = Child; var newChild = content as IControl; if (content != null && newChild == null) { var dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default; // We have content and it isn't a control, so if the new data template is the same // as the old data template, try to recycle the existing child control to display // the new data. if (dataTemplate == _dataTemplate && dataTemplate.SupportsRecycling) { newChild = oldChild; } else { _dataTemplate = dataTemplate; newChild = _dataTemplate.Build(content); } } else { _dataTemplate = null; } return(newChild); }
/// <summary> /// Materializes a piece of data based on a data template. /// </summary> /// <param name="control">The control materializing the data template.</param> /// <param name="data">The data.</param> /// <returns>The data materialized as a control.</returns> public static IControl MaterializeDataTemplate(this IControl control, object data) { if (data == null) { return(null); } else { var asControl = data as IControl; if (asControl != null) { return(asControl); } else { IDataTemplate template = control.FindDataTemplate(data); IControl result; if (template != null) { result = template.Build(data); } else { result = FuncDataTemplate.Default.Build(data); } NameScope.SetNameScope((Control)result, new NameScope()); return(result); } } }
/// <summary> /// Materializes a piece of data based on a data template. /// </summary> /// <param name="control">The control materializing the data template.</param> /// <param name="data">The data.</param> /// <returns>The data materialized as a control.</returns> public static IControl MaterializeDataTemplate(this IControl control, object data) { IDataTemplate template = control.FindDataTemplate(data); IControl result; if (template != null) { result = template.Build(data); if (result != null && result.DataContext == null) { result.DataContext = data; } } else if (data is IControl) { result = (IControl)data; } else { result = DataTemplate.Default.Build(data); } return(result); }
/// <summary> /// Creates the container for an item. /// </summary> /// <param name="item">The item.</param> /// <param name="itemTemplate">An optional item template.</param> /// <returns>The created container control.</returns> protected virtual IControl CreateContainer(object item, IDataTemplate itemTemplate) { if (item == null) { return(null); } else if (itemTemplate != null && itemTemplate.Match(item)) { var result = itemTemplate.Build(item); result.DataContext = item; return(result); } else { return(Owner.MaterializeDataTemplate(item)); } }
/// <summary> /// Creates the child control. /// </summary> /// <returns>The child control or null.</returns> protected virtual IControl CreateChild() { var content = Content; var oldChild = Child; var newChild = content as IControl; if (content != null && newChild == null) { // We have content and it isn't a control, so first try to recycle the existing // child control to display the new data by querying if the template that created // the child can recycle items and that it also matches the new data. if (oldChild != null && _dataTemplate != null && _dataTemplate.SupportsRecycling && _dataTemplate.Match(content)) { newChild = oldChild; } else { // We couldn't recycle an existing control so find a data template for the data // and use it to create a control. _dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default; newChild = _dataTemplate.Build(content); // Try to give the new control its own name scope. var controlResult = newChild as Control; if (controlResult != null) { NameScope.SetNameScope(controlResult, new NameScope()); } } } else { _dataTemplate = null; } return(newChild); }
/// <summary> /// Updates the <see cref="Child"/> control based on the control's <see cref="Content"/>. /// </summary> /// <remarks> /// Usually the <see cref="Child"/> control is created automatically when /// <see cref="ApplyTemplate"/> is called; however for this to happen, the control needs to /// be attached to a logical tree (if the control is not attached to the logical tree, it /// is reasonable to expect that the DataTemplates needed for the child are not yet /// available). This method forces the <see cref="Child"/> control's creation at any point, /// and is particularly useful in unit tests. /// </remarks> public void UpdateChild() { var content = Content; var oldChild = Child; var newChild = content as IControl; if (content != null && newChild == null) { // We have content and it isn't a control, so first try to recycle the existing // child control to display the new data by querying if the template that created // the child can recycle items and that it also matches the new data. if (oldChild != null && _dataTemplate != null && _dataTemplate.SupportsRecycling && _dataTemplate.Match(content)) { newChild = oldChild; } else { // We couldn't recycle an existing control so find a data template for the data // and use it to create a control. _dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default; newChild = _dataTemplate.Build(content); // Try to give the new control its own name scope. var controlResult = newChild as Control; if (controlResult != null) { NameScope.SetNameScope(controlResult, new NameScope()); } } } else { _dataTemplate = null; } // Remove the old child if we're not recycling it. if (oldChild != null && newChild != oldChild) { VisualChildren.Remove(oldChild); } // Set the DataContext if the data isn't a control. if (!(content is IControl)) { DataContext = content; } // Update the Child. if (newChild == null) { Child = null; } else if (newChild != oldChild) { ((ISetInheritanceParent)newChild).SetParent(this); Child = newChild; if (oldChild?.Parent == this) { LogicalChildren.Remove(oldChild); } if (newChild.Parent == null) { var templatedLogicalParent = TemplatedParent as ILogical; if (templatedLogicalParent != null) { ((ISetLogicalParent)newChild).SetParent(templatedLogicalParent); } else { LogicalChildren.Add(newChild); } } VisualChildren.Add(newChild); } _createdChild = true; }
/// <summary> /// Creates the child control. /// </summary> /// <returns>The child control or null.</returns> protected virtual IControl CreateChild() { var content = Content; var oldChild = Child; var newChild = content as IControl; if (content != null && newChild == null) { // We have content and it isn't a control, so first try to recycle the existing // child control to display the new data by querying if the template that created // the child can recycle items and that it also matches the new data. if (oldChild != null && _dataTemplate != null && _dataTemplate.SupportsRecycling && _dataTemplate.Match(content)) { newChild = oldChild; } else { // We couldn't recycle an existing control so find a data template for the data // and use it to create a control. _dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default; newChild = _dataTemplate.Build(content); // Try to give the new control its own name scope. var controlResult = newChild as Control; if (controlResult != null) { NameScope.SetNameScope(controlResult, new NameScope()); } } } else { _dataTemplate = null; } return newChild; }
/// <summary> /// Creates the container for an item. /// </summary> /// <param name="item">The item.</param> /// <param name="itemTemplate">An optional item template.</param> /// <returns>The created container control.</returns> protected virtual IControl CreateContainer(object item, IDataTemplate itemTemplate) { if (item == null) { return null; } else if (itemTemplate != null && itemTemplate.Match(item)) { var result = itemTemplate.Build(item); result.DataContext = item; return result; } else { return Owner.MaterializeDataTemplate(item); } }