Пример #1
0
        //// Steps for resolving a ViewModel to View
        //// 1. Find all ViewModel requested Views matching the ControlKind
        //// 2. Find all Views supporting the ViewModel matching the ControlKind
        //// 3. Find all Views supporting the ViewModel without ControlKind

        /// <summary>
        /// Look up the ViewDescriptor for this presentable model and ControlKind
        /// </summary>
        /// <param name="self"></param>
        /// <param name="tk"></param>
        /// <param name="requestedControlKind"></param>
        /// <returns></returns>
        public static ViewDescriptor GetViewDescriptor(
            this ViewModelDescriptor self,
            Toolkit tk,
            ControlKind requestedControlKind)
        {
            // Checks
            if (self == null)
            {
                throw new ArgumentNullException("self");
            }

            #region Cache Management
            PrimeCaches(tk, self.ReadOnlyContext);

            var key = new ViewDescriptorCache.Key(self.ViewModelRef, tk, requestedControlKind);
            if (_viewDescriptorCache.ContainsKey(key))
            {
                return(_viewDescriptorCache[key]);
            }
            #endregion

            // If the ViewModel has a more specific DefaultKind respect its choice
            if (self.DefaultEditorKind != null &&
                requestedControlKind != null &&
                self.DefaultEditorKind.AndParents().Select(i => i.ExportGuid).Contains(requestedControlKind.ExportGuid))
            {
                if (requestedControlKind != self.DefaultEditorKind)
                {
                    Logging.Log.DebugFormat("Using more specific default kind: {0} -> {1}", requestedControlKind.Name, self.DefaultEditorKind.Name);
                }
                requestedControlKind = self.DefaultEditorKind;
            }
            else
            {
                requestedControlKind = self.SecondaryControlKinds
                                       .FirstOrDefault(
                    sck => sck.AndParents()
                    .Select(i => i.ExportGuid)
                    .Contains(requestedControlKind.ExportGuid)
                    ) ?? requestedControlKind;
            }

            ViewDescriptor result = null;

            ICollection <ViewDescriptor> candidates;
            if (requestedControlKind != null)
            {
                candidates = _viewCaches[tk].GetDescriptors(requestedControlKind);
            }
            else
            {
                candidates = _viewCaches[tk].GetDescriptors();
            }

            if (candidates.Count == 0)
            {
                // Try parent
                var parent = self.ViewModelRef.Parent != null?self.ViewModelRef.Parent.GetViewModelDescriptor() : null;

                if (parent != null)
                {
                    result = GetViewDescriptor(parent, tk, requestedControlKind);
                }
                else
                {
                    Logging.Log.WarnFormat("Couldn't find ViewDescriptor for '{1}' matching ControlKind: '{0}'", requestedControlKind, self.ViewModelRef);
                }
            }
            else if (candidates.Count == 1)
            {
                result = candidates.First();
            }
            else
            {
                var allTypes = GetAllTypes(self);
                // As allTypes is sorted from most specific to least specific first or default is perfect.
                var match = allTypes.SelectMany(t => candidates.Where(c => c.SupportedViewModels.Contains(t))).FirstOrDefault();

                // Try the most common
                if (match == null)
                {
                    match = allTypes.SelectMany(t => candidates.Where(c => c.SupportedViewModels.Count == 0)).FirstOrDefault();
                }

                // Log a warning if nothing found
                if (match == null)
                {
                    Logging.Log.WarnFormat("Couldn't find ViewDescriptor for '{1}' matching ControlKind: '{0}'", requestedControlKind, self.GetType().FullName);
                }
                result = match;
            }

            _viewDescriptorCache[key] = result;
            return(result);
        }