diff --git a/MobileBlazorBindings.sln b/MobileBlazorBindings.sln index 8101be8c..86bcb7dd 100644 --- a/MobileBlazorBindings.sln +++ b/MobileBlazorBindings.sln @@ -162,6 +162,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HybridMsalAuthApp.macOS", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HybridMsalAuthApp.Windows", "samples\HybridMsalAuthSample\HybridMsalAuthApp.Windows\HybridMsalAuthApp.Windows.csproj", "{7F72AEB6-7077-4F58-A3EB-BC668E8EEECF}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.MobileBlazorBindings.Forms", "src\Microsoft.MobileBlazorBindings.Forms\Microsoft.MobileBlazorBindings.Forms.csproj", "{4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -921,6 +923,18 @@ Global {7F72AEB6-7077-4F58-A3EB-BC668E8EEECF}.Release|iPhone.Build.0 = Release|Any CPU {7F72AEB6-7077-4F58-A3EB-BC668E8EEECF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {7F72AEB6-7077-4F58-A3EB-BC668E8EEECF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Debug|iPhone.Build.0 = Debug|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Release|Any CPU.Build.0 = Release|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Release|iPhone.ActiveCfg = Release|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Release|iPhone.Build.0 = Release|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263}.Release|iPhoneSimulator.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -995,6 +1009,7 @@ Global {D3B0F2E0-E1A6-4F9F-8B64-5EB147B1B817} = {EDBF7495-7557-457A-96FF-DB68D4B57C2F} {84EBDBF2-0E83-4D20-BCEA-F00FF716F2F6} = {EDBF7495-7557-457A-96FF-DB68D4B57C2F} {7F72AEB6-7077-4F58-A3EB-BC668E8EEECF} = {EDBF7495-7557-457A-96FF-DB68D4B57C2F} + {4A24D736-ED4E-4C61-8C24-2B8CEFC1B263} = {175AB6E2-5FB5-4C15-94C2-DCA2EE6B0703} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A645A7FF-3F09-414D-A391-7E50C3597F05} diff --git a/src/Microsoft.MobileBlazorBindings.Forms/CascadingEditContext.cs b/src/Microsoft.MobileBlazorBindings.Forms/CascadingEditContext.cs new file mode 100644 index 00000000..774588fc --- /dev/null +++ b/src/Microsoft.MobileBlazorBindings.Forms/CascadingEditContext.cs @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using Microsoft.AspNetCore.Components.Rendering; +using System; + +namespace Microsoft.MobileBlazorBindings.Forms +{ + public class CascadingEditContext : ComponentBase + { + private EditContext _editContext; + private bool _hasSetEditContextExplicitly; + + [Parameter] + public EditContext EditContext + { + get => _editContext; + set + { + _editContext = value; + _hasSetEditContextExplicitly = value != null; + } + } + + [Parameter] public object Model { get; set; } + + [Parameter] public RenderFragment ChildContent { get; set; } + + protected override void OnParametersSet() + { + if (_hasSetEditContextExplicitly && Model != null) + { + throw new InvalidOperationException($"{nameof(CascadingEditContext)} requires a {nameof(Model)} " + + $"parameter, or an {nameof(EditContext)} parameter, but not both."); + } + else if (!_hasSetEditContextExplicitly && Model == null) + { + throw new InvalidOperationException($"{nameof(CascadingEditContext)} requires either a {nameof(Model)} " + + $"parameter, or an {nameof(EditContext)} parameter, please provide one of these."); + } + + // Update _editContext if we don't have one yet, or if they are supplying a + // potentially new EditContext, or if they are supplying a different Model + if (Model != null && Model != _editContext?.Model) + { + _editContext = new EditContext(Model!); + } + } + + protected override void BuildRenderTree(RenderTreeBuilder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + // If _editContext changes, tear down and recreate all descendants. + // This is so we can safely use the IsFixed optimization on CascadingValue, + // optimizing for the common case where _editContext never changes. + builder.OpenRegion(_editContext.GetHashCode()); + + builder.OpenComponent>(0); + builder.AddAttribute(1, "IsFixed", true); + builder.AddAttribute(2, "Value", _editContext); + builder.AddAttribute(3, "ChildContent", ChildContent?.Invoke(_editContext)); + builder.CloseComponent(); + + builder.CloseRegion(); + } + } +} diff --git a/src/Microsoft.MobileBlazorBindings.Forms/InputViewWrapper.cs b/src/Microsoft.MobileBlazorBindings.Forms/InputViewWrapper.cs new file mode 100644 index 00000000..019cd8e5 --- /dev/null +++ b/src/Microsoft.MobileBlazorBindings.Forms/InputViewWrapper.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using Microsoft.AspNetCore.Components; +using System.Collections.Generic; +using System.Linq; +using XF = Xamarin.Forms; + +namespace Microsoft.MobileBlazorBindings.Forms +{ + public abstract class InputViewWrapper : ViewWrapper + { + /// + /// Gets or sets a value that indicates the number of device-independent units that should be in between characters in the text displayed by the Entry. Applies to Text and Placeholder. + /// + /// + /// The number of device-independent units that should be in between characters in the text. + /// + [Parameter] public double? CharacterSpacing { get; set; } + /// + /// Gets or sets a value that indicates whether user should be prevented from modifying the text. Default is . + /// + /// + /// If , user cannot modify text. Else, . + /// + [Parameter] public bool? IsReadOnly { get; set; } + /// + /// Gets or sets a value that controls whether spell checking is enabled. + /// + /// + /// if spell checking is enabled. Otherwise . + /// + [Parameter] public bool? IsSpellCheckEnabled { get; set; } + /// + /// Gets or sets the maximum allowed length of input. + /// + /// + /// An integer in the interval [0,int.MaxValue]. The default value is Int.MaxValue. + /// + [Parameter] public int? MaxLength { get; set; } + /// + /// Gets or sets the text that is displayed when the control is empty. + /// + /// + /// The text that is displayed when the control is empty. + /// + [Parameter] public string Placeholder { get; set; } + /// + /// Gets or sets the color of the placeholder text. + /// + /// + /// The color of the placeholder text. + /// + [Parameter] public XF.Color? PlaceholderColor { get; set; } + /// + /// Gets or sets the text color. + /// + [Parameter] public XF.Color? TextColor { get; set; } + [Parameter] public XF.TextTransform? TextTransform { get; set; } + + private IEnumerable> InputViewProperties + { + get + { + yield return new KeyValuePair(nameof(CharacterSpacing), CharacterSpacing); + yield return new KeyValuePair(nameof(IsReadOnly), IsReadOnly); + yield return new KeyValuePair(nameof(IsSpellCheckEnabled), IsSpellCheckEnabled); + yield return new KeyValuePair(nameof(MaxLength), MaxLength); + yield return new KeyValuePair(nameof(Placeholder), Placeholder); + yield return new KeyValuePair(nameof(PlaceholderColor), PlaceholderColor); + yield return new KeyValuePair(nameof(TextColor), TextColor); + yield return new KeyValuePair(nameof(TextTransform), TextTransform); + } + } + + protected override IEnumerable> WrappedProperties + { + get + { + return base.WrappedProperties.Concat(InputViewProperties); + } + } + } +} diff --git a/src/Microsoft.MobileBlazorBindings.Forms/Microsoft.MobileBlazorBindings.Forms.csproj b/src/Microsoft.MobileBlazorBindings.Forms/Microsoft.MobileBlazorBindings.Forms.csproj new file mode 100644 index 00000000..10f1650f --- /dev/null +++ b/src/Microsoft.MobileBlazorBindings.Forms/Microsoft.MobileBlazorBindings.Forms.csproj @@ -0,0 +1,13 @@ + + + + netstandard2.0 + 3.0 + Forms and validation support for Experimental Mobile Blazor Bindings. + + + + + + + diff --git a/src/Microsoft.MobileBlazorBindings.Forms/SubmitButton.razor b/src/Microsoft.MobileBlazorBindings.Forms/SubmitButton.razor new file mode 100644 index 00000000..acd91142 --- /dev/null +++ b/src/Microsoft.MobileBlazorBindings.Forms/SubmitButton.razor @@ -0,0 +1,34 @@ +@inherits ViewWrapper + +