//// 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); }
//// 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; }
//// 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.ViewModelTypeRef, 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 type = Type.GetType(self.ViewModelTypeRef); var parent = type != null && type.BaseType != null ? type.BaseType.GetViewModelDescriptor(self.ReadOnlyContext) : null; if (parent != null) { result = GetViewDescriptor(parent, tk, requestedControlKind); } else { Logging.Log.WarnFormat("Couldn't find View for '{1}' matching ControlKind: '{0}'", requestedControlKind, self.ViewModelTypeRef); } } else if (candidates.Count == 1) { result = candidates.First(); } else { var allTypes = GetAllTypes(self); // As allTypes is sorted from most specific to least specific, so first or default is perfect. var match = allTypes.SelectMany(vmType => candidates.Where(candidate => { var viewType = Type.GetType(candidate.ControlTypeRef, throwOnError: false); if (viewType == null) return false; var supportedViewModels = viewType.GetInterfaces() .Where(ifType => ifType.IsGenericType && ifType.GetGenericTypeDefinition() == typeof(IHasViewModel<>)) .Select(ifType => ifType.GetGenericArguments().Single()); return supportedViewModels.Contains(vmType); })).FirstOrDefault(); // Log a warning if nothing found if (match == null) { Logging.Log.WarnFormat("Couldn't find View for '{1}' matching ControlKind: '{0}'", requestedControlKind, self.ViewModelTypeRef); } result = match; } _viewDescriptorCache[key] = result; return result; }