Dictionary <char, List <string> > _charToSimpleHighContrastNames; //this dictionary serves to link the first letter of the theme-dependent resource to the simple high contrast names that start with that letter. //The objective is to reduce the amount of strings we try to find in the resource (probably a minor improvement in performance but it's something) /// <summary> /// Tries to find the resourceKey in the Generic.xaml resources of the assembly. Note: the resource currently need to be defined in Project/Themes/generic.xaml /// </summary> /// <param name="assemblyWhereGenericXamlIsLocated">The assembly where we will look into.</param> /// <param name="resourceKey">The resource to find in the Assembly's resources.</param> /// <returns>The resource associated with the given key in the given assembly's resources.</returns> internal object TryFindResourceInGenericXaml(Assembly assemblyWhereGenericXamlIsLocated, object resourceKey) { ResourceDictionary resourceDictionary = null; if (_assemblyToResourceDictionary.ContainsKey(assemblyWhereGenericXamlIsLocated)) { resourceDictionary = _assemblyToResourceDictionary[assemblyWhereGenericXamlIsLocated]; } else { #if !BRIDGE string assemblyName = assemblyWhereGenericXamlIsLocated.GetName().Name; #else string assemblyName = INTERNAL_BridgeWorkarounds.GetAssemblyNameWithoutCallingGetNameMethod(assemblyWhereGenericXamlIsLocated); #endif assemblyName = assemblyName.Replace(" ", "ǀǀ").Replace(".", "ǀǀ"); string factoryTypeName = MakeTitleCase("ǀǀ" + assemblyName + "ǀǀComponentǀǀThemesǀǀGenericǀǀXamlǀǀFactory"); Type resourceDictionaryFactoryType = assemblyWhereGenericXamlIsLocated.GetType(factoryTypeName); if (resourceDictionaryFactoryType != null) { resourceDictionary = (ResourceDictionary)resourceDictionaryFactoryType.GetMethod("Instantiate").Invoke(null, null); _assemblyToResourceDictionary.Add(assemblyWhereGenericXamlIsLocated, resourceDictionary); } } if (resourceDictionary != null && resourceDictionary.ContainsKey(resourceKey)) { return(resourceDictionary[resourceKey]); } return(null); }
public void UpdateRow(int index, object item) { foreach (var prop in item.GetType().GetProperties()) { object newValue = null; try { #if CSHTML5 if (INTERNAL_BridgeWorkarounds.MethodInfoIsStatic_SimulatorCompatible(prop.GetMethod)) #else if (prop.GetMethod.IsStatic) //have to check for that because for some reason Bridge throws an Exception when trying to call prop.GetValue(item) when it is a static property. #endif { newValue = prop.GetValue(null); } else { newValue = prop.GetValue(item); } } catch (Exception) { } this.updateCell(index, this.columnIndexes[prop.Name], newValue); } }
internal static object INTERNAL_ConvertFromString(string keyTimeCode) { try { if (keyTimeCode == "Uniform") { throw new NotImplementedException("The Value \"Uniform\" for keyTime is not supported yet."); } else if (keyTimeCode == "Paced") { throw new NotImplementedException("The Value \"Paced\" for keyTime is not supported yet."); } else if (keyTimeCode.EndsWith("%")) { throw new NotImplementedException("The percentage values for keyTime are not supported yet."); } else { #if BRIDGE TimeSpan timeSpan = INTERNAL_BridgeWorkarounds.TimeSpanParse(keyTimeCode, false); #else TimeSpan timeSpan = TimeSpan.Parse(keyTimeCode); #endif return(new KeyTime(timeSpan)); } } catch (Exception ex) { throw new Exception("Invalid KeyTime: " + keyTimeCode, ex); } }
/// <summary> /// Returns the first child of the specified type (recursively). /// </summary> /// <typeparam name="T">The type to lookup.</typeparam> /// <param name="parent">The parent element.</param> /// <returns>The first child of the specified type.</returns> public static T GetChildOfType <T>(UIElement parent) where T : UIElement { if (parent == null || parent.INTERNAL_VisualChildrenInformation == null) { return(null); } foreach (INTERNAL_VisualChildInformation visualChildInformation in #if BRIDGE INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(parent.INTERNAL_VisualChildrenInformation) #else parent.INTERNAL_VisualChildrenInformation.Values #endif ) { var child = visualChildInformation.INTERNAL_UIElement; var result = (child as T) ?? GetChildOfType <T>(child); if (result != null) { return(result); } } return(null); }
global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() { #if BRIDGE return(INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(_visualStateGroups).GetEnumerator()); #else return(_visualStateGroups.Values.GetEnumerator()); #endif }
public IEnumerator <VisualStateGroup> GetEnumerator() { #if BRIDGE return(INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(_visualStateGroups).GetEnumerator()); #else return(_visualStateGroups.Values.GetEnumerator()); #endif }
internal override void UpdateValue() { if (DependencyProperty != null) { //this.ValueType = this.DependencyProperty.GetTargetType(); UpdateValueAndIsBroken(((DependencyObject)Source).GetValue(DependencyProperty), CheckIsBroken()); } else if (PropertyInfo != null) { //TODO: this.ValueType = PropertyInfo.PropertyType; //this.ValueType = null; //todo: don't know what this is for try { #if BRIDGE //Bridge throws an exception when trying to call GetValue through PropertyInfo.GetValue on a Static Property while putting an instance as a parameter (which should not be the case in my opinion). //Because of that, we need to check whether the property is Static and then accordingly call GetValue with either null or the instance as a parameter. object propertyValue = null; MethodInfo methodInfo = PropertyInfo.GetMethod; if (INTERNAL_BridgeWorkarounds.MethodInfoIsStatic_SimulatorCompatible(methodInfo)) { propertyValue = PropertyInfo.GetValue(null); } else { propertyValue = PropertyInfo.GetValue(this.Source); } UpdateValueAndIsBroken(propertyValue, CheckIsBroken()); #else UpdateValueAndIsBroken(PropertyInfo.GetValue(this.Source), CheckIsBroken()); #endif } catch { UpdateValueAndIsBroken(null, CheckIsBroken()); } } else if (FieldInfo != null) { try { UpdateValueAndIsBroken(FieldInfo.GetValue(this.Source), CheckIsBroken()); } catch { UpdateValueAndIsBroken(null, CheckIsBroken()); } } else if (BindsDirectlyToSource) { this.UpdateValueAndIsBroken(Source, CheckIsBroken(BindsDirectlyToSource)); } else { //this.ValueType = null; this.UpdateValueAndIsBroken(null, CheckIsBroken()); } }
Dictionary <char, List <string> > _charToSimpleHighContrastNames; //this dictionary serves to link the first letter of the theme-dependent resource to the simple high contrast names that start with that letter. //The objective is to reduce the amount of strings we try to find in the resource (probably a minor improvement in performance but it's something) /// <summary> /// Tries to find the resourceKey in the Generic.xaml resources of the assembly. Note: the resource currently need to be defined in Project/Themes/generic.xaml /// </summary> /// <param name="assemblyWhereGenericXamlIsLocated">The assembly where we will look into.</param> /// <param name="resourceKey">The resource to find in the Assembly's resources.</param> /// <returns>The resource associated with the given key in the given assembly's resources.</returns> internal object TryFindResourceInGenericXaml(Assembly assemblyWhereGenericXamlIsLocated, object resourceKey) { ResourceDictionary resourceDictionary = null; if (_assemblyToResourceDictionary.ContainsKey(assemblyWhereGenericXamlIsLocated)) { resourceDictionary = _assemblyToResourceDictionary[assemblyWhereGenericXamlIsLocated]; } else { #if !BRIDGE string assemblyName = assemblyWhereGenericXamlIsLocated.GetName().Name; // todo: instead of the following if, make it so that the Core project can generate the .g.cs files by itself (JSIL version, Bridge works fine) instead of relying on an external project (called DotNetForHtml5.Core.Styles). Note: given what the name of the assembly is, it should still be shortened to remove everything after the first comma. //Fixing the assemblyName so that the default styles can be found (the generic.xaml file that contains the default styles is located in a different project with a different namespace): if (assemblyName == "SLMigration.CSharpXamlForHtml5" || assemblyName == "CSharpXamlForHtml5" || assemblyName == "SLMigration.CSharpXamlForHtml5, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" || assemblyName == "CSharpXamlForHtml5, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null") { assemblyName = "DotNetForHtml5.Core.Styles"; //Note: this is the name of the assembly where the default styles are defined (project DotNetForHtml5.Core.Styles in the DotNetForHtml5 solution). } #else string assemblyName = INTERNAL_BridgeWorkarounds.GetAssemblyNameWithoutCallingGetNameMethod(assemblyWhereGenericXamlIsLocated); #endif assemblyName = assemblyName.Replace(" ", "ǀǀ").Replace(".", "ǀǀ"); string factoryTypeName = MakeTitleCase("ǀǀ" + assemblyName + "ǀǀComponentǀǀThemesǀǀGenericǀǀXamlǀǀFactory"); Type resourceDictionaryFactoryType = assemblyWhereGenericXamlIsLocated.GetType(factoryTypeName); #if CSHTML5BLAZOR if (resourceDictionaryFactoryType == null) { if (assemblyName == "OpenSilver") //We do this part because OpenSilver uses the generic.xaml.g.cs of the CSHTML5 Migration edition which in consequence has a different namespace than it would have if it was directly defined as xaml in OpenSilver. { assemblyName = "Cshtml5ǀǀMigration"; factoryTypeName = MakeTitleCase("ǀǀ" + assemblyName + "ǀǀComponentǀǀThemesǀǀGenericǀǀXamlǀǀFactory"); resourceDictionaryFactoryType = assemblyWhereGenericXamlIsLocated.GetType(factoryTypeName); } else if (assemblyName == "OpenSilverǀǀUwpCompatible") //We do this part because OpenSilver uses the generic.xaml.g.cs of the CSHTML5 Migration edition which in consequence has a different namespace than it would have if it was directly defined as xaml in OpenSilver. { assemblyName = "Cshtml5"; factoryTypeName = MakeTitleCase("ǀǀ" + assemblyName + "ǀǀComponentǀǀThemesǀǀGenericǀǀXamlǀǀFactory"); resourceDictionaryFactoryType = assemblyWhereGenericXamlIsLocated.GetType(factoryTypeName); } } #endif if (resourceDictionaryFactoryType != null) { resourceDictionary = (ResourceDictionary)resourceDictionaryFactoryType.GetMethod("Instantiate").Invoke(null, null); _assemblyToResourceDictionary.Add(assemblyWhereGenericXamlIsLocated, resourceDictionary); } } if (resourceDictionary != null && resourceDictionary.ContainsKey(resourceKey)) { return(resourceDictionary[resourceKey]); } return(null); }
///// <summary> ///// Subtracts the specified Windows.UI.Xaml.Duration from this Windows.UI.Xaml.Duration. ///// </summary> ///// <param name="duration">The Windows.UI.Xaml.Duration to subtract from this Windows.UI.Xaml.Duration.</param> ///// <returns>The subtracted Windows.UI.Xaml.Duration.</returns> //public Duration Subtract(Duration duration); ///// <summary> ///// Converts a Windows.UI.Xaml.Duration to a System.String representation. ///// </summary> ///// <returns>A System.String representation of this Windows.UI.Xaml.Duration.</returns> //public override string ToString(); internal static object INTERNAL_ConvertFromString(string p) { #if BRIDGE TimeSpan timeSpan = INTERNAL_BridgeWorkarounds.TimeSpanParse(p); #else TimeSpan timeSpan = TimeSpan.Parse(p); #endif return(new Duration(timeSpan)); }
/// <summary> /// Returns an enumerator that iterates through the ResourceDictionary. /// </summary> /// <returns>A System.Collections.Generic.Dictionary{object,object}.Enumerator structure for the ResourceDictionary.</returns> IEnumerator IEnumerable.GetEnumerator() { //todo (maybe): change the enumerator so that it also goes through the elements of the merged Dictionaries #if BRIDGE return(INTERNAL_BridgeWorkarounds.GetDictionaryEnumerator(_resourcesContainer)); #else return(_resourcesContainer.GetEnumerator()); #endif }
static object FindPage(Uri uri) { string assemblyName; string instancierName; GetXamlFileAssociatedClassInstancierName(uri, out assemblyName, out instancierName); //this method should only accept .xaml files (imo), it returns the name of the class we generated during the compilation, built from the assembly(gotten from either the uri, or the startingAssembly) and the file name. #if BRIDGE foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (INTERNAL_BridgeWorkarounds.GetAssemblyNameWithoutCallingGetNameMethod(assembly) == assemblyName) { Type type = assembly.GetType(instancierName); if (type != null) { MethodInfo methodInfo = type.GetMethod("Instantiate"); return(methodInfo.Invoke(null, null)); } break; } } #else #if OPENSILVER if (true) #elif BRIDGE if (CSHTML5.Interop.IsRunningInTheSimulator) #endif { foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (assembly.GetName().Name == assemblyName) { Type type = assembly.GetType(instancierName); if (type != null) { MethodInfo methodInfo = type.GetMethod("Instantiate"); return(methodInfo.Invoke(null, null)); } break; } } } else { object assembly = CSHTML5.Interop.ExecuteJavaScript(@"JSIL.GetAssembly($0, true)", assemblyName); object type = CSHTML5.Interop.ExecuteJavaScript(@"JSIL.GetTypeFromAssembly($0, $1)", assembly, instancierName); if (!IsNullOrUndefined(type)) { object method = CSHTML5.Interop.ExecuteJavaScript(@"$0.GetMethod('Instantiate')", type); return(CSHTML5.Interop.ExecuteJavaScript("$0.Invoke(null, null)", method)); } } #endif return(null); }
static object ConvertTimeSpanFromString(string str) { try { #if BRIDGE TimeSpan returnValue = INTERNAL_BridgeWorkarounds.TimeSpanParse(str); #else TimeSpan returnValue = TimeSpan.Parse(str); #endif return(returnValue); } catch { throw new Exception("Xaml exception: cannot convert \"" + str + "\" to TimeSpan. " + AdviseToFixTheError); } }
internal void INTERNAL_UpdateBindingsSource() { if (_bindingExpressions != null) { foreach (BindingExpression bindingExpression in #if BRIDGE INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(_bindingExpressions) #else _bindingExpressions.Values #endif ) { bindingExpression.OnSourceAvailable(); } } }
public VisualStateGroup this[int index] { get { #if BRIDGE return(INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(_visualStateGroups).ElementAt(index)); #else return(_visualStateGroups.Values.ElementAt(index)); #endif } set { //todo: refresh the VisualStates throw new NotImplementedException(); _visualStateGroups[_visualStateGroups.Keys.ElementAt(index)] = value; } }
public static IEnumerable GetAllRootUIElements() // IMPORTANT: This is called via reflection from the "Visual Tree Inspector" of the Simulator. If you rename or remove it, be sure to update the Simulator accordingly! { // Include the main window: yield return(Window.Current); // And all the popups: foreach (var popupRoot in #if BRIDGE INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(PopupRootIdentifierToInstance) #else PopupRootIdentifierToInstance.Values #endif ) { yield return(popupRoot); } }
///// <summary> ///// Subtracts the specified Windows.UI.Xaml.Duration from this Windows.UI.Xaml.Duration. ///// </summary> ///// <param name="duration">The Windows.UI.Xaml.Duration to subtract from this Windows.UI.Xaml.Duration.</param> ///// <returns>The subtracted Windows.UI.Xaml.Duration.</returns> //public Duration Subtract(Duration duration); ///// <summary> ///// Converts a Windows.UI.Xaml.Duration to a System.String representation. ///// </summary> ///// <returns>A System.String representation of this Windows.UI.Xaml.Duration.</returns> //public override string ToString(); internal static object INTERNAL_ConvertFromString(string p) { if (p.ToLower() == "forever") { return(Duration.Forever); } if (p.ToLower() == "automatic") { return(Duration.Automatic); } #if BRIDGE TimeSpan timeSpan = INTERNAL_BridgeWorkarounds.TimeSpanParse(p); #else TimeSpan timeSpan = TimeSpan.Parse(p); #endif return(new Duration(timeSpan)); }
public int IndexOf(VisualStateGroup item) { int i = 0; while (i < _visualStateGroups.Count) { #if BRIDGE if (INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(_visualStateGroups).ElementAt(i) == item) #else if (_visualStateGroups.Values.ElementAt(i) == item) #endif { return(i); } ++i; } return(-1); }
internal static object INTERNAL_ConvertFromString(string colorcode) { try { // Check if the color is a named color: if (!colorcode.StartsWith("#")) { Colors.INTERNAL_ColorsEnum namedColor = (Colors.INTERNAL_ColorsEnum)Enum.Parse(typeof(Colors.INTERNAL_ColorsEnum), colorcode, true); // Note: "TryParse" does not seem to work in JSIL. return(INTERNAL_ConvertFromInt32((int)namedColor)); } else { colorcode = colorcode.Replace("#", ""); if (colorcode.Length == 6) // This is becaue XAML is tolerant when the user has forgot the alpha channel (eg. #DDDDDD for Gray). { colorcode = "FF" + colorcode; } #if !BRIDGE int colorAsInt = int.Parse(colorcode.Replace("#", ""), NumberStyles.HexNumber); #else int colorAsInt; if (CSHTML5.Interop.IsRunningInTheSimulator) { colorcode = colorcode.Replace("#", ""); colorAsInt = INTERNAL_BridgeWorkarounds.HexToInt_SimulatorOnly(colorcode); } else { colorAsInt = Script.Write <int>("parseInt({0}, 16);", colorcode.Replace("#", "")); } #endif return(INTERNAL_ConvertFromInt32(colorAsInt)); } } catch (Exception ex) { throw new Exception("Invalid color: " + colorcode, ex); } }
static string[] GetListOfLoadedAssemblies() { string[] listOfAssemblies; if (CSHTML5.Interop.IsRunningInTheSimulator) { #if !BRIDGE listOfAssemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToArray(); #else listOfAssemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => INTERNAL_BridgeWorkarounds.GetAssemblyNameWithoutCallingGetNameMethod(a)).ToArray(); #endif } else { #if !BRIDGE listOfAssemblies = JSIL.Verbatim.Expression("Object.keys(JSIL.AssemblyShortNames)"); #else listOfAssemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => GetAssemblyName(a.FullName)).ToArray();//Script.Write<string[]>("Object.keys(JSIL.AssemblyShortNames);"); #endif } return(listOfAssemblies); }
static void AttachVisualChild_Private(UIElement child, UIElement parent) { // // THIS IS WHAT THE FINAL STRUCTURE IN THE DOM TREE WILL LOOK LIKE: // // domElementWhereToPlaceChildStuff // --- [wrapperForChild] // --- --- [innerDivOfWrapperForChild] // --- --- --- [additionalOutsideDivForMargins, aka BoxSizing] // --- --- --- --- outerDomElement // //-------------------------------------------------------- // APPLY IMPLICIT AND DEFAULT STYLES: //-------------------------------------------------------- #if PERFSTAT var t = Performance.now(); #endif //See if the child has a Style, if not, try to find an implicitStyle for its Type. FrameworkElement childAsFrameworkElement = child as FrameworkElement; if (childAsFrameworkElement != null) { if (childAsFrameworkElement.Style == null) { //----------------------------- // APPLY IMPLICIT STYLE IF ANY: //----------------------------- Style style = null; //Note if anyone wonders: if type B inherits from type A, an Implicit Style defined for type A is ignored by elements of type B (tested in an SL project). if (UpdateElementInheritedImplicitStyles(childAsFrameworkElement, (FrameworkElement)parent)) { Type childType = child.GetType(); foreach (ResourceDictionary resourceDictionary in childAsFrameworkElement.INTERNAL_InheritedImplicitStyles) // Note: "INTERNAL_InheritedImplicitStyles" is not null because the method above returned True. { if (resourceDictionary.ContainsKey(childType)) { style = resourceDictionary[childType] as Style; break; } } } if (style != null) { childAsFrameworkElement.Style = style; childAsFrameworkElement.INTERNAL_IsImplicitStyle = true; //Note: it is important that we do this AFTER setting the Style property to the ImplicitStyle because the setter of the Style Property sets it to false to avoid removing styles that are not implicit. } } //Add the effect of the setters of the default Style on the child: Style childDefaultStyle = childAsFrameworkElement.INTERNAL_defaultStyle; if (childDefaultStyle != null) { //---------------------------- // APPLY DEFAULT STYLE IF ANY: //---------------------------- //get the list of setters of the currently applied style on the element and of the default style: Dictionary <DependencyProperty, Setter> normalStyleDictionary = null; bool childHasStyle = childAsFrameworkElement.Style != null; if (childHasStyle) { normalStyleDictionary = childAsFrameworkElement.Style.GetDictionaryOfSettersFromStyle(); } Dictionary <DependencyProperty, Setter> defaultStyleDictionary = childDefaultStyle.GetDictionaryOfSettersFromStyle(); //for all the setters the default style has, that are not on properties already affected by the normal style, we apply them like a normal style (we basically do the same as what we do on each setter in FrameworkElement.Style_Changed): foreach (DependencyProperty prop in #if BRIDGE INTERNAL_BridgeWorkarounds.GetDictionaryKeys_SimulatorCompatible(defaultStyleDictionary) #else defaultStyleDictionary.Keys #endif ) { if (!childHasStyle || !normalStyleDictionary.ContainsKey(prop)) { Setter setter = defaultStyleDictionary[prop]; childDefaultStyle.SetterValueChanged -= childAsFrameworkElement.StyleSetterValueChanged; childDefaultStyle.SetterValueChanged += childAsFrameworkElement.StyleSetterValueChanged; INTERNAL_PropertyStorage storage = INTERNAL_PropertyStore.GetStorageOrCreateNewIfNotExists(childAsFrameworkElement, setter.Property); INTERNAL_PropertyStore.SetLocalStyleValue(storage, setter.Value); } } } } #if PERFSTAT Performance.Counter("VisualTreeManager: Apply implicit and default styles", t); #endif //-------------------------------------------------------- // PREPARE THE PARENT: //-------------------------------------------------------- #if PERFSTAT var t0 = Performance.now(); #endif // Prepare the parent DOM structure so that it is ready to contain the child (for example, in case of a grid, we need to (re)create the rows and columns where to place the elements). //parent.INTERNAL_UpdateDomStructureIfNecessary(); object domElementWhereToPlaceChildStuff = (parent.GetDomElementWhereToPlaceChild(child) ?? parent.INTERNAL_InnerDomElement); // A "wrapper for child" is sometimes needed between the child and the parent (for example in case of a grid). It is usually one or more DIVs that fit in-between the child and the parent, and that are used to position the child within the parent. object innerDivOfWrapperForChild; object wrapperForChild = parent.CreateDomChildWrapper(domElementWhereToPlaceChildStuff, out innerDivOfWrapperForChild); bool comparison1 = (wrapperForChild == null); // Note: we need due to a bug of JSIL where translation fails if we do not use this temp variable. bool comparison2 = (innerDivOfWrapperForChild == null); // Note: we need due to a bug of JSIL where translation fails if we do not use this temp variable. bool doesParentRequireToCreateAWrapperForEachChild = (!comparison1 && !comparison2); // Note: The result is "True" for complex structures such as tables, false otherwise (cf. documentation in "INTERNAL_VisualChildInformation" class). #if PERFSTAT Performance.Counter("VisualTreeManager: Prepare the parent", t0); #endif //-------------------------------------------------------- // CONTINUE WITH THE OTHER STEPS (OR DEFER TO WHEN THE ELEMENT IS VISIBLE, IF THE OPTIMIZATION TO NOT LOAD COLLAPSED CONTROLS IS ENABLED): //-------------------------------------------------------- if (!EnableOptimizationWhereCollapsedControlsAreNotLoaded || child.Visibility != Visibility.Collapsed) { AttachVisualChild_Private_FinalStepsOnlyIfControlIsVisible( child, parent, doesParentRequireToCreateAWrapperForEachChild, innerDivOfWrapperForChild, domElementWhereToPlaceChildStuff, wrapperForChild); } else { child.INTERNAL_DeferredLoadingWhenControlBecomesVisible = () => { AttachVisualChild_Private_FinalStepsOnlyIfControlIsVisible( child, parent, doesParentRequireToCreateAWrapperForEachChild, innerDivOfWrapperForChild, domElementWhereToPlaceChildStuff, wrapperForChild); }; } }
static void AttachVisualChild_Private_MainSteps(UIElement child, UIElement parent, bool doesParentRequireToCreateAWrapperForEachChild, object innerDivOfWrapperForChild, object domElementWhereToPlaceChildStuff, object wrapperForChild) { #if REWORKLOADED if (INTERNAL_VisualTreeOperation.Current.Root == null) { INTERNAL_VisualTreeOperation.Current.Root = parent; } #endif //#if CSHTML5BLAZOR && DEBUG // string childIndentity = child + (child != null ? " (" + child.GetHashCode() + ")" : ""); // string parentIndentity = parent + (parent != null ? " (" + parent.GetHashCode() + ")" : ""); // Console.WriteLine("OPEN SILVER DEBUG: VisualTreeManager : AttachVisualChild_Private_FinalStepsOnlyIfControlIsVisible: " + childIndentity + " attached to " + parentIndentity); //#endif //-------------------------------------------------------- // CREATE THE DIV FOR THE MARGINS (OPTIONAL): //-------------------------------------------------------- #if PERFSTAT var t1 = Performance.now(); #endif // Determine if an additional DIV for handling margins is needed: object additionalOutsideDivForMargins = null; var margin = ((FrameworkElement)child).Margin; bool containsNegativeMargins = (margin.Left < 0d || margin.Top < 0d || margin.Right < 0d || margin.Bottom < 0d); #if ONLY_ADD_DIV_FOR_MARGINS_WHEN_MARGINS_NOT_ZERO bool isADivForMarginsNeeded = !(parent is Canvas) && !(child is Inline) && child is FrameworkElement; // Note: In a Canvas, we don't want to add the additional DIV because there are no margins and we don't want to interfere with the pointer events by creating an additional DIV. if (isADivForMarginsNeeded) { var horizontalAlign = ((FrameworkElement)child).HorizontalAlignment; var verticalAlign = ((FrameworkElement)child).VerticalAlignment; isADivForMarginsNeeded = !(margin.Left == 0 && margin.Top == 0 && margin.Right == 0 && margin.Bottom == 0 && horizontalAlign == HorizontalAlignment.Stretch && verticalAlign == VerticalAlignment.Stretch); } #else bool isADivForMarginsNeeded = !(parent is Canvas) && // Note: In a Canvas, we don't want to add the additional DIV because there are no margins and we don't want to interfere with the pointer events by creating an additional DIV. !(child is Inline); // Note: inside a TextBlock we do not want the HTML DIV because we want to create HTML SPAN elements only (otherwise there would be unwanted line returns). #endif if (isADivForMarginsNeeded) { // Determine where to place it: object whereToPlaceDivForMargins = (doesParentRequireToCreateAWrapperForEachChild ? innerDivOfWrapperForChild : domElementWhereToPlaceChildStuff); // Create and append the DIV for handling margins and append: additionalOutsideDivForMargins = INTERNAL_HtmlDomManager.CreateDomElementAndAppendIt("div", whereToPlaceDivForMargins, parent); //todo: check if the third parameter should be the child or the parent (make something with margins and put a mouseenter in the parent then see if the event is triggered). // Style the DIV for handling margins: var style = INTERNAL_HtmlDomManager.GetDomElementStyleForModification(additionalOutsideDivForMargins); style.boxSizing = "border-box"; if (child is FrameworkElement && (((FrameworkElement)child).HorizontalAlignment == HorizontalAlignment.Stretch && double.IsNaN(((FrameworkElement)child).Width))) { if (!containsNegativeMargins) { style.width = "100%"; } } if (child is FrameworkElement && (((FrameworkElement)child).VerticalAlignment == VerticalAlignment.Stretch && double.IsNaN(((FrameworkElement)child).Height))) { style.height = "100%"; } } #if PERFSTAT Performance.Counter("VisualTreeManager: Create the DIV for the margin", t1); #endif //-------------------------------------------------------- // PREPARE THE CHILD: //-------------------------------------------------------- #if PERFSTAT var t2 = Performance.now(); #endif // Determine where to place the child: object whereToPlaceTheChild = (isADivForMarginsNeeded ? additionalOutsideDivForMargins : (doesParentRequireToCreateAWrapperForEachChild ? innerDivOfWrapperForChild : domElementWhereToPlaceChildStuff)); // Set the "Parent" property of the Child (IMPORTANT: we need to do that before child.CreateDomElement because the type of the parent is used to display the child correctly): child.INTERNAL_VisualParent = parent; // Set the "ParentWindow" property so that the element knows where to display popups: child.INTERNAL_ParentWindow = parent.INTERNAL_ParentWindow; // Create and append the DOM structure of the Child: object domElementWhereToPlaceGrandChildren = null; object outerDomElement; bool isChildAControl = child is Control; if (child.INTERNAL_HtmlRepresentation == null) { bool hasTemplate = isChildAControl && ((Control)child).HasTemplate; if (hasTemplate) { outerDomElement = ((Control)child).CreateDomElementForControlTemplate(whereToPlaceTheChild, out domElementWhereToPlaceGrandChildren); } else { outerDomElement = child.CreateDomElement(whereToPlaceTheChild, out domElementWhereToPlaceGrandChildren); } } else { outerDomElement = INTERNAL_HtmlDomManager.CreateDomFromStringAndAppendIt(child.INTERNAL_HtmlRepresentation, whereToPlaceTheChild, child); } // Initialize the "Width" and "Height" of the child DOM structure: if (child is FrameworkElement) { FrameworkElement.INTERNAL_InitializeOuterDomElementWidthAndHeight(((FrameworkElement)child), outerDomElement); } // Update the DOM structure of the Child (for example, if the child is a Grid, this will render its rows and columns): child.INTERNAL_UpdateDomStructureIfNecessary(); // For debugging purposes (to better read the output html), add a class to the outer DIV that tells us the corresponding type of the element (Border, StackPanel, etc.): INTERNAL_HtmlDomManager.SetDomElementAttribute(outerDomElement, "class", child.GetType().ToString()); #if PERFSTAT Performance.Counter("VisualTreeManager: Prepare the child", t2); #endif //-------------------------------------------------------- // REMEMBER ALL INFORMATION FOR FUTURE USE: //-------------------------------------------------------- #if PERFSTAT var t3 = Performance.now(); #endif // Remember the DIVs: child.INTERNAL_OuterDomElement = outerDomElement; child.INTERNAL_InnerDomElement = domElementWhereToPlaceGrandChildren; child.INTERNAL_AdditionalOutsideDivForMargins = additionalOutsideDivForMargins ?? outerDomElement; child.INTERNAL_InnerDivOfTheChildWrapperOfTheParentIfAny = doesParentRequireToCreateAWrapperForEachChild ? innerDivOfWrapperForChild : null; // Remember the information about the "VisualChildren": if (parent.INTERNAL_VisualChildrenInformation == null) { parent.INTERNAL_VisualChildrenInformation = new Dictionary <UIElement, INTERNAL_VisualChildInformation>(); } parent.INTERNAL_VisualChildrenInformation.Add(child, new INTERNAL_VisualChildInformation() { INTERNAL_UIElement = child, INTERNAL_OptionalChildWrapper_OuterDomElement = wrapperForChild, INTERNAL_OptionalChildWrapper_ChildWrapperInnerDomElement = innerDivOfWrapperForChild }); #if PERFSTAT Performance.Counter("VisualTreeManager: Remember all info for future use", t3); #endif //-------------------------------------------------------- // HANDLE SPECIAL CASES: //-------------------------------------------------------- #if PERFSTAT var t4 = Performance.now(); #endif // If we are inside a canvas, we set the position to "absolute": if (parent is Canvas) { INTERNAL_HtmlDomManager.GetDomElementStyleForModification(outerDomElement).position = "absolute"; //todo: test if this works properly } UIElement.SynchronizeForceInheritProperties(child, parent); #if REVAMPPOINTEREVENTS UIElement.INTERNAL_UpdateCssPointerEvents(child); #else // If the current element is inside a Grid, we need to explicitly set its CSS property "PointerEvents=auto" because its parent child wrapper has "PointerEvents=none" in order to prevent its child wrappers from overlapping each other and thus preventing clicks on some children. if (parent is Grid && child is FrameworkElement) //todo: generalize this code so that we have no hard-reference on the Grid control, and third-party controls can use the same mechanics. { var frameworkElement = ((FrameworkElement)child); FrameworkElement.INTERNAL_UpdateCssPointerEventsPropertyBasedOnIsHitTestVisibleAndIsEnabled(frameworkElement, frameworkElement.IsHitTestVisible, frameworkElement.IsEnabled); } #endif // Reset the flag that tells if we have already applied the RenderTransformOrigin (this is useful to ensure that the default RenderTransformOrigin is (0,0) like in normal XAML, instead of (0.5,0.5) like in CSS): child.INTERNAL_RenderTransformOriginHasBeenApplied = false; #if PERFSTAT Performance.Counter("VisualTreeManager: Handle special cases", t4); #endif //-------------------------------------------------------- // HANDLE EVENTS: //-------------------------------------------------------- #if PERFSTAT var t5 = Performance.now(); #endif // Register DOM events if any: child.INTERNAL_AttachToDomEvents(); #if PERFSTAT Performance.Counter("VisualTreeManager: Handle events", t5); #endif //-------------------------------------------------------- // HANDLE INHERITED PROPERTIES: //-------------------------------------------------------- #if PERFSTAT var t6 = Performance.now(); #endif // Get the Inherited properties and pass them to the direct children: foreach (DependencyProperty dependencyProperty in #if BRIDGE INTERNAL_BridgeWorkarounds.GetDictionaryKeys_SimulatorCompatible(parent.INTERNAL_AllInheritedProperties) #else parent.INTERNAL_AllInheritedProperties.Keys #endif ) { bool recursively = false; // We don't want a recursion here because the "Attach" method is already recursive due to the fact that we raise property changed on the Children property, which causes to reattach the subtree. INTERNAL_PropertyStorage storage = parent.INTERNAL_AllInheritedProperties[dependencyProperty]; child.SetInheritedValue(dependencyProperty, INTERNAL_PropertyStore.GetEffectiveValue(storage), recursively); } #if PERFSTAT Performance.Counter("Handle inherited properties", t6); #endif //-------------------------------------------------------- // SET "ISLOADED" PROPERTY AND CALL "ONATTACHED" EVENT: //-------------------------------------------------------- // Tell the control that it is now present into the visual tree: child._isLoaded = true; // Raise the "OnAttached" event: child.INTERNAL_OnAttachedToVisualTree(); // IMPORTANT: Must be done BEFORE "RaiseChangedEventOnAllDependencyProperties" (for example, the ItemsControl uses this to initialize its visual) //-------------------------------------------------------- // RENDER THE ELEMENTS BY APPLYING THE CSS PROPERTIES: //-------------------------------------------------------- // Defer rendering when the control is not visible to when becomes visible (note: when this option is enabled, we do not apply the CSS properties of the UI elements that are not visible. Those property are applied later, when the control becomes visible. This option results in improved performance.) bool enableDeferredRenderingOfCollapsedControls = EnableOptimizationWhereCollapsedControlsAreNotRendered || EnableOptimizationWhereCollapsedControlsAreLoadedLast || EnableOptimizationWhereCollapsedControlsAreNotLoaded; if (enableDeferredRenderingOfCollapsedControls && !child.IsVisible) { child.INTERNAL_DeferredRenderingWhenControlBecomesVisible = () => { RenderElementsAndRaiseChangedEventOnAllDependencyProperties(child); }; } else { RenderElementsAndRaiseChangedEventOnAllDependencyProperties(child); } //-------------------------------------------------------- // HANDLE BINDING: //-------------------------------------------------------- #if PERFSTAT var t9 = Performance.now(); #endif child.INTERNAL_UpdateBindingsSource(); #if PERFSTAT Performance.Counter("VisualTreeManager: Handle binding", t9); #endif //-------------------------------------------------------- // HANDLE TABINDEX: //-------------------------------------------------------- // For GotFocus and LostFocus to work, the DIV specified by "INTERNAL_OptionalSpecifyDomElementConcernedByFocus" // (or the OuterDomElement otherwise) needs to have the "tabIndex" attribute set. Therefore we need to always set // it (unless IsTabStop is False) to its current value (default is Int32.MaxValue). At the time when this code was // written, there was no way to automatically call the "OnChanged" on a dependency property if no value was set. #if !REWORKLOADED // IMPORTANT: This needs to be done AFTER the "OnApplyTemplate" (for example, the TextBox sets the "INTERNAL_OptionalSpecifyDomElementConcernedByFocus" in the "OnApplyTemplate"). if (isChildAControl) { if (!(child is ContentPresenter) && !(child is TextBlock)) //ContentPresenter should not count in tabbing, as well as TextBlock (especially since TextBlock is not supposed to be a Control). { Control.TabIndexProperty_MethodToUpdateDom(child, ((Control)child).TabIndex); } } #endif //-------------------------------------------------------- // APPLY THE VISIBILITY: //-------------------------------------------------------- Visibility childVisibility = child.Visibility; if (childVisibility == Visibility.Collapsed) { UIElement.INTERNAL_ApplyVisibility(child, childVisibility); } //-------------------------------------------------------- // RAISE THE "SIZECHANGED" EVENT: //-------------------------------------------------------- #if !REWORKLOADED #if PERFSTAT var t10 = Performance.now(); #endif // Raise the "SizeChanged" event: (note: in XAML, the "SizeChanged" event is called before the "Loaded" event) // IMPORTANT: This event needs to be raised AFTER the "OnApplyTemplate" and AFTER the "IsLoaded=true" (for example, it is used in the ScrollBar implementation). if (child is FrameworkElement) { ((FrameworkElement)child).INTERNAL_SizeChangedWhenAttachedToVisualTree(); } #if PERFSTAT Performance.Counter("VisualTreeManager: Raise size changed event", t10); #endif //-------------------------------------------------------- // RAISE THE "LOADED" EVENT: //-------------------------------------------------------- #if PERFSTAT var t11 = Performance.now(); #endif // Raise the "Loaded" event: (note: in XAML, the "loaded" event of the children is called before the "loaded" event of the parent) if (child is FrameworkElement) { ((FrameworkElement)child).INTERNAL_RaiseLoadedEvent(); } child.StartManagingPointerPositionForPointerExitedEventIfNeeded(); #if PERFSTAT Performance.Counter("VisualTreeManager: Raise Loaded event", t11); #endif #else INTERNAL_VisualTreeOperation.Current.Enqueue(child); #endif }
private static void Style_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { var frameworkElement = (FrameworkElement)d; if (!frameworkElement.INTERNAL_DoNotApplyStyle) { Style newStyle = (Style)e.NewValue; Style oldStyle = (Style)e.OldValue; Dictionary <DependencyProperty, Setter> oldStyleDictionary = new Dictionary <DependencyProperty, Setter>(); if (oldStyle != null) { oldStyleDictionary = oldStyle.GetDictionaryOfSettersFromStyle(); } Dictionary <DependencyProperty, Setter> newStyleDictionary = new Dictionary <DependencyProperty, Setter>(); if (newStyle != null) { newStyleDictionary = newStyle.GetDictionaryOfSettersFromStyle(); } #if PERFSTAT var t0 = Performance.now(); #endif frameworkElement.RecursivelyUnregisterFromStyleChangedEvents(oldStyle); #if PERFSTAT Performance.Counter("RecursivelyUnregisterFromStyleChangedEvents", t0); #endif #if PERFSTAT var t1 = Performance.now(); #endif frameworkElement.RecursivelyRegisterToStyleChangedEvents(newStyle); #if PERFSTAT Performance.Counter("RecursivelyRegisterToStyleChangedEvents", t1); #endif foreach (Setter oldSetter in #if BRIDGE INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(oldStyleDictionary) #else oldStyleDictionary.Values #endif ) { if (oldSetter.Property != null) // Note: it can be null for example in the XAML text editor during design time, because the "DependencyPropertyConverter" class returns "null". { if (!newStyleDictionary.ContainsKey(oldSetter.Property)) { INTERNAL_PropertyStorage storage = INTERNAL_PropertyStore.GetStorage(d, oldSetter.Property, createAndSaveNewStorageIfNotExists: false); //the createAndSaveNewStorageIfNotExists's value should have no actual meaning here because the PropertyStorage should have been created when applying the style. INTERNAL_PropertyStore.ResetLocalStyleValue(storage); } } // Reset the information that tells which Style the Setter belongs to (this is used so that when the Value of the Setter changes, the Setter can notify its parent Style): oldSetter.INTERNAL_ParentStyle = null; } foreach (Setter newSetter in #if BRIDGE INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(newStyleDictionary) #else newStyleDictionary.Values #endif ) { if (newSetter.Property != null) // Note: it can be null for example in the XAML text editor during design time, because the "DependencyPropertyConverter" class returns "null". { if (!oldStyleDictionary.ContainsKey(newSetter.Property) || oldStyleDictionary[newSetter.Property] != newSetter.Value) { INTERNAL_PropertyStorage storage = INTERNAL_PropertyStore.GetStorage(frameworkElement, newSetter.Property, createAndSaveNewStorageIfNotExists: true); //the createAndSaveNewStorageIfNotExists's value should have no actual meaning here because the PropertyStorage should have been created when applying the style. INTERNAL_PropertyStore.SetLocalStyleValue(storage, newSetter.Value); } } // Tell the setter which Style it belongs to, so that when the Value of the Setter changes, it can notify the parent Style: newSetter.INTERNAL_ParentStyle = newStyle; } } }
static void DetachVisualChidrenRecursively(UIElement element) { // Debug: //System.Diagnostics.Debug.WriteLine("Detached: " + element.GetType().Name); if (element._pointerExitedEventManager != null) { //todo: use element.INTERNAL_IsPointerInside for the test then set it to false. //bool wasPointerInElement = Convert.ToBoolean(CSHTML5.Interop.ExecuteJavaScript("$0.data_IsMouseInside", element.INTERNAL_OuterDomElement)); //if (wasPointerInElement) if (element.INTERNAL_isPointerInside) { #if MIGRATION //element.ProcessOnMouseLeave(CSHTML5.Interop.ExecuteJavaScript("window.lastPointerPosition.event")); MouseEventArgs eventArgs = new MouseEventArgs(); element.OnMouseLeave(eventArgs); element.OnMouseLeave_ForHandledEventsToo(eventArgs); #else PointerRoutedEventArgs eventArgs = new PointerRoutedEventArgs(); element.OnPointerExited(eventArgs);//CSHTML5.Interop.ExecuteJavaScript("window.lastPointerPosition.event")); element.OnPointerExited_ForHandledEventsToo(eventArgs); #endif } element.isAlreadySubscribedToMouseEnterAndLeave = false; element.INTERNAL_isPointerInside = false; } // Call the "OnDetached" of the element. This is particularly useful for elements to clear any references they have to DOM elements. For example, the Grid will use it to set its _tableDiv to null. element.INTERNAL_OnDetachedFromVisualTree(); //We detach the events from the dom element: element.INTERNAL_DetachFromDomEvents(); // Call the "Unloaded" event: (note: in XAML, the "unloaded" event of the parent is called before the "unloaded" event of the children) element._isLoaded = false; if (element is FrameworkElement) { ((FrameworkElement)element).INTERNAL_RaiseUnloadedEvent(); } // Traverse all elements recursively: if (element.INTERNAL_VisualChildrenInformation != null) { foreach (INTERNAL_VisualChildInformation childInfo in #if BRIDGE INTERNAL_BridgeWorkarounds.GetDictionaryValues_SimulatorCompatible(element.INTERNAL_VisualChildrenInformation) #else element.INTERNAL_VisualChildrenInformation.Values #endif ) { DetachVisualChidrenRecursively(childInfo.INTERNAL_UIElement); } } DependencyObject oldParent = element.INTERNAL_VisualParent; // Reset all visual-tree related information: element.INTERNAL_OuterDomElement = null; element.INTERNAL_InnerDomElement = null; element.INTERNAL_VisualParent = null; element.INTERNAL_VisualChildrenInformation = null; element.INTERNAL_AdditionalOutsideDivForMargins = null; element.INTERNAL_DeferredRenderingWhenControlBecomesVisible = null; element.INTERNAL_DeferredLoadingWhenControlBecomesVisible = null; // We reset the inherited properties since the element is no longer attached to its parent element.ResetInheritedProperties(); if (oldParent != null) { UIElement.SynchronizeForceInheritProperties(element, oldParent); } }
internal static object INTERNAL_ConvertFromString(string colorString) { string trimmedString = colorString.Trim(); if (!string.IsNullOrEmpty(trimmedString) && (trimmedString[0] == '#')) { string tokens = trimmedString.Substring(1); if (tokens.Length == 6) // This is becaue XAML is tolerant when the user has forgot the alpha channel (eg. #DDDDDD for Gray). { tokens = "FF" + tokens; } #if NETSTANDARD int color; if (int.TryParse(tokens, NumberStyles.HexNumber, NumberFormatInfo.CurrentInfo, out color)) { return(INTERNAL_ConvertFromInt32(color)); } #else // BRIDGE int color; if (CSHTML5.Interop.IsRunningInTheSimulator) { color = INTERNAL_BridgeWorkarounds.HexToInt_SimulatorOnly(tokens); } else { color = Script.Write <int>("parseInt({0}, 16);", tokens); } return(INTERNAL_ConvertFromInt32(color)); #endif } else if (trimmedString != null && trimmedString.StartsWith("sc#", StringComparison.Ordinal)) { string tokens = trimmedString.Substring(3); char[] separators = new char[1] { ',' }; string[] words = tokens.Split(separators); float[] values = new float[4]; for (int i = 0; i < 3; i++) { values[i] = Convert.ToSingle(words[i]); } if (words.Length == 4) { values[3] = Convert.ToSingle(words[3]); return(Color.FromScRgb(values[0], values[1], values[2], values[3])); } else { return(Color.FromScRgb(1.0f, values[0], values[1], values[2])); } } else { // Check if the color is a named color Colors.INTERNAL_ColorsEnum namedColor; if (Enum.TryParse(trimmedString, true, out namedColor)) { return(INTERNAL_ConvertFromInt32((int)namedColor)); } } throw new Exception(string.Format("Invalid color: {0}", colorString)); }