Пример #1
0
 /// <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));
     }
 }
Пример #2
0
        public static IDataTemplate?FindDataTemplate(
            this IControl control,
            object data,
            IDataTemplate?primary = null)
        {
            if (primary?.Match(data) == true)
            {
                return(primary);
            }

            var currentTemplateHost = control as ILogical;

            while (currentTemplateHost != null)
            {
                if (currentTemplateHost is IDataTemplateHost hostCandidate && hostCandidate.IsDataTemplatesInitialized)
                {
                    foreach (IDataTemplate dt in hostCandidate.DataTemplates)
                    {
                        if (dt.Match(data))
                        {
                            return(dt);
                        }
                    }
                }

                currentTemplateHost = currentTemplateHost.LogicalParent;
            }

            var global = AvaloniaLocator.Current.GetService <IGlobalDataTemplates>();

            if (global != null && global.IsDataTemplatesInitialized)
            {
                foreach (IDataTemplate dt in global.DataTemplates)
                {
                    if (dt.Match(data))
                    {
                        return(dt);
                    }
                }
            }

            return(null);
        }
Пример #3
0
        /// <summary>
        /// Find a data template that matches a piece of data.
        /// </summary>
        /// <param name="control">The control searching for the data template.</param>
        /// <param name="data">The data.</param>
        /// <param name="primary">
        /// An optional primary template that can will be tried before the DataTemplates in the
        /// tree are searched.
        /// </param>
        /// <returns>The data template or null if no matching data template was found.</returns>
        public static IDataTemplate FindDataTemplate(
            this IControl control,
            object data,
            IDataTemplate primary = null)
        {
            if (primary?.Match(data) == true)
            {
                return(primary);
            }

            foreach (var i in control.GetSelfAndLogicalAncestors().OfType <IDataTemplateHost>())
            {
                if (i.IsDataTemplatesInitialized)
                {
                    foreach (IDataTemplate dt in i.DataTemplates)
                    {
                        if (dt.Match(data))
                        {
                            return(dt);
                        }
                    }
                }
            }

            IGlobalDataTemplates global = AvaloniaLocator.Current.GetService <IGlobalDataTemplates>();

            if (global != null)
            {
                if (global.IsDataTemplatesInitialized)
                {
                    foreach (IDataTemplate dt in global.DataTemplates)
                    {
                        if (dt.Match(data))
                        {
                            return(dt);
                        }
                    }
                }
            }

            return(null);
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        /// <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;
        }
Пример #6
0
 /// <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);
     }
 }