From b25cd876059dd030d780374589a04fb03264e19b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E9=95=87=E6=B1=90?= <8907060@qq.com> Date: Tue, 2 Jan 2018 21:34:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=B8=8B=E6=8B=89=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E7=BB=84=E4=BB=B6=EF=BC=8C=E6=94=AF=E6=8C=81lambda?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readme.md | 4 +- .../Services/Dtos/Customers/CustomersDto.cs | 10 ++- .../Util.Samples.Webs/Views/Home/Demo.cshtml | 7 +- src/Util.Ui.Abstractions/Services/IContext.cs | 4 +- .../Services/IUiService.cs | 7 -- .../Extensions/Extensions.HtmlHelper.cs | 6 +- .../Extensions/Extensions.UiService.cs | 13 +-- .../Material/Extensions/Extensions.Form.cs | 2 +- .../Extensions/Extensions.TextBox.cs | 2 +- .../Material/Forms/Models/ModelSelect.cs | 84 +++++++++++++++++++ .../Material/Forms/Renders/SelectRender.cs | 2 +- .../Material/Services/IUiService.cs | 17 ++++ .../Material/Services/UiService.cs | 32 +++++++ src/Util.Ui.Core/Attributes/ModelAttribute.cs | 27 ++++++ .../Extensions/Extensions.Component.Form.cs | 2 +- src/Util.Ui.Core/Internal/Helper.cs | 44 ++++++++++ .../{UiService.cs => UiServiceBase.cs} | 6 +- src/Util/Helpers/Reflection.cs | 10 +-- src/Util/Helpers/String.Tools.cs | 14 ++++ test/Util.Tests/Helpers/StringTest.Tools.cs | 20 ++++- .../Material/Forms/TextBoxTest.cs | 1 + 21 files changed, 272 insertions(+), 42 deletions(-) delete mode 100644 src/Util.Ui.Abstractions/Services/IUiService.cs rename src/Util.Ui.Angular/{ => Material}/Extensions/Extensions.TextBox.cs (96%) create mode 100644 src/Util.Ui.Angular/Material/Forms/Models/ModelSelect.cs create mode 100644 src/Util.Ui.Angular/Material/Services/IUiService.cs create mode 100644 src/Util.Ui.Angular/Material/Services/UiService.cs create mode 100644 src/Util.Ui.Core/Attributes/ModelAttribute.cs create mode 100644 src/Util.Ui.Core/Internal/Helper.cs rename src/Util.Ui.Core/Services/{UiService.cs => UiServiceBase.cs} (75%) diff --git a/readme.md b/readme.md index c2bec466..c4ff761e 100644 --- a/readme.md +++ b/readme.md @@ -395,6 +395,7 @@ https://github.com/dotnetcore/util/ - 组件基类 [已发布] - TagHelper基类 [已发布] - 图标 - 集成了Material Design和Font Awesome图标集 [已发布] + - 下拉列表 - 基于Material Select组件 [已发布] - 按钮 [开发中] - 文本框 [开发中] - 权限 [待启动] @@ -438,4 +439,5 @@ https://github.com/dotnetcore/util/ - 2017年10月29日,更新了加密操作(Util.Helpers.Encrypt,集成了MD5,DES,AES,RSA加密操作)及单元测试。 - 2017年10月30日,更新了Url参数生成器(Util.Parameters)及单元测试。 - 2017年10月31日,更新了支付宝条码支付操作(Util.Biz.Payments/Alipay)及单元测试。 -- 2017年11月15日,更新了EF Core调试日志(Util.Datas/Logs)及单元测试。 \ No newline at end of file +- 2017年11月15日,更新了EF Core调试日志(Util.Datas/Logs)及单元测试。 +- 2018年1月2日,更新了下拉列表组件(Util.Ui.Angular/Material/Forms)及单元测试。 \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Services/Dtos/Customers/CustomersDto.cs b/sample/Util.Samples.Webs/Services/Dtos/Customers/CustomersDto.cs index b3273c19..2faf80b8 100644 --- a/sample/Util.Samples.Webs/Services/Dtos/Customers/CustomersDto.cs +++ b/sample/Util.Samples.Webs/Services/Dtos/Customers/CustomersDto.cs @@ -1,7 +1,10 @@ using System; +using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; using Util.Applications.Dtos; +using Util.Biz.Enums; +using Util.Ui.Attributes; namespace Donau.Services.Dtos.Customers { /// @@ -29,17 +32,16 @@ namespace Donau.Services.Dtos.Customers { /// /// 余额 /// - [Required(ErrorMessage = "余额不能为空")] - [Display( Name = "余额" )] [DataMember] - public decimal Balance { get; set; } + public string Balance { get; set; } /// /// 性别 /// [Display( Name = "性别" )] [DataMember] - public int? Gender { get; set; } + [Model(Ignore = true)] + public Gender Gender { get; set; } /// /// 联系电话 diff --git a/sample/Util.Samples.Webs/Views/Home/Demo.cshtml b/sample/Util.Samples.Webs/Views/Home/Demo.cshtml index 98bce002..aca7ba2f 100644 --- a/sample/Util.Samples.Webs/Views/Home/Demo.cshtml +++ b/sample/Util.Samples.Webs/Views/Home/Demo.cshtml @@ -1,4 +1,5 @@ -@{ +@model Donau.Services.Dtos.Customers.CustomersDto +@{ ViewData["Title"] = "Tile"; }
@@ -23,9 +24,9 @@ - @(Html.Ui().Select().Placeholder( "民族" ).Enum().Multiple()) - + @Html.Ui().Select(t => t.Gender ) + diff --git a/src/Util.Ui.Abstractions/Services/IContext.cs b/src/Util.Ui.Abstractions/Services/IContext.cs index a62c8340..317259a5 100644 --- a/src/Util.Ui.Abstractions/Services/IContext.cs +++ b/src/Util.Ui.Abstractions/Services/IContext.cs @@ -5,11 +5,11 @@ namespace Util.Ui.Services { /// /// Ui上下文 /// - public interface IContext { + public interface IContext { /// /// HtmlHelper /// - IHtmlHelper Helper { get; } + IHtmlHelper Helper { get; } /// /// Html编码 /// diff --git a/src/Util.Ui.Abstractions/Services/IUiService.cs b/src/Util.Ui.Abstractions/Services/IUiService.cs deleted file mode 100644 index 11a83807..00000000 --- a/src/Util.Ui.Abstractions/Services/IUiService.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Util.Ui.Services { - /// - /// 组件服务 - /// - public interface IUiService { - } -} diff --git a/src/Util.Ui.Angular/Extensions/Extensions.HtmlHelper.cs b/src/Util.Ui.Angular/Extensions/Extensions.HtmlHelper.cs index 1f2fe3ec..7b8eb099 100644 --- a/src/Util.Ui.Angular/Extensions/Extensions.HtmlHelper.cs +++ b/src/Util.Ui.Angular/Extensions/Extensions.HtmlHelper.cs @@ -1,7 +1,7 @@ using System.Text.Encodings.Web; using Microsoft.AspNetCore.Mvc.Rendering; using Util.Helpers; -using Util.Ui.Services; +using Util.Ui.Material.Services; namespace Util.Ui.Extensions { /// @@ -12,8 +12,8 @@ namespace Util.Ui.Extensions { /// Angular组件服务 /// /// HtmlHelper - public static IUiService Ui( this IHtmlHelper helper ) { - return new UiService( helper,Ioc.Create() ); + public static IUiService Ui( this IHtmlHelper helper ) { + return new UiService( helper, Ioc.Create() ); } } } diff --git a/src/Util.Ui.Angular/Extensions/Extensions.UiService.cs b/src/Util.Ui.Angular/Extensions/Extensions.UiService.cs index 52f106fd..da16a3b1 100644 --- a/src/Util.Ui.Angular/Extensions/Extensions.UiService.cs +++ b/src/Util.Ui.Angular/Extensions/Extensions.UiService.cs @@ -3,6 +3,7 @@ using Util.Ui.Components; using Util.Ui.Material.Buttons; using Util.Ui.Material.Forms; using Util.Ui.Material.Icons; +using Util.Ui.Material.Services; using Util.Ui.Services; namespace Util.Ui.Extensions { @@ -14,7 +15,7 @@ namespace Util.Ui.Extensions { /// 图标 ///
/// 组件服务 - public static IIcon Icon( this IUiService service ) { + public static IIcon Icon( this IUiService service ) { return new Icon(); } @@ -22,7 +23,7 @@ namespace Util.Ui.Extensions { /// 下拉列表 ///
/// 组件服务 - public static ISelect Select( this IUiService service ) { + public static ISelect Select( this IUiService service ) { return new Select(); } @@ -31,7 +32,7 @@ namespace Util.Ui.Extensions { /// /// 组件服务 /// 文本 - public static Util.Ui.Material.Buttons.IButton Button( this IUiService service,string text ) { + public static Util.Ui.Material.Buttons.IButton Button( this IUiService service, string text ) { return new Button().Text( text ); } @@ -39,7 +40,7 @@ namespace Util.Ui.Extensions { /// 文本框 /// /// 组件服务 - public static ITextBox TextBox( this IUiService service ) { + public static ITextBox TextBox( this IUiService service ) { return new TextBox(); } @@ -47,8 +48,8 @@ namespace Util.Ui.Extensions { /// 表单 /// /// 组件服务 - public static IForm Form( this IUiService service ) { - if( !( service is IContext context )) + public static IForm Form( this IUiService service ) { + if( !( service is IContext context ) ) throw new NotImplementedException( "组件服务必须实现Util.Ui.Services.IContext" ); return new Form( context.Helper.ViewContext.Writer, context.Encoder ); } diff --git a/src/Util.Ui.Angular/Material/Extensions/Extensions.Form.cs b/src/Util.Ui.Angular/Material/Extensions/Extensions.Form.cs index ada54ef2..025cdcfc 100644 --- a/src/Util.Ui.Angular/Material/Extensions/Extensions.Form.cs +++ b/src/Util.Ui.Angular/Material/Extensions/Extensions.Form.cs @@ -11,7 +11,7 @@ namespace Util.Ui.Material.Extensions { /// public static partial class Extensions { /// - /// 设置占位符 + /// 设置占位提示符 /// /// 组件类型 /// 组件实例 diff --git a/src/Util.Ui.Angular/Extensions/Extensions.TextBox.cs b/src/Util.Ui.Angular/Material/Extensions/Extensions.TextBox.cs similarity index 96% rename from src/Util.Ui.Angular/Extensions/Extensions.TextBox.cs rename to src/Util.Ui.Angular/Material/Extensions/Extensions.TextBox.cs index 84007645..393af2d2 100644 --- a/src/Util.Ui.Angular/Extensions/Extensions.TextBox.cs +++ b/src/Util.Ui.Angular/Material/Extensions/Extensions.TextBox.cs @@ -2,7 +2,7 @@ using Util.Ui.Components.Internal; using Util.Ui.Configs; -namespace Util.Ui.Extensions { +namespace Util.Ui.Material.Extensions { /// /// 文本框扩展 /// diff --git a/src/Util.Ui.Angular/Material/Forms/Models/ModelSelect.cs b/src/Util.Ui.Angular/Material/Forms/Models/ModelSelect.cs new file mode 100644 index 00000000..aaffd8f9 --- /dev/null +++ b/src/Util.Ui.Angular/Material/Forms/Models/ModelSelect.cs @@ -0,0 +1,84 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.Linq.Expressions; +using System.Reflection; +using Util.Helpers; +using Util.Ui.Extensions; +using Util.Ui.Internal; +using Util.Ui.Material.Extensions; + +namespace Util.Ui.Material.Forms.Models { + /// + /// 模型下拉列表 + /// + /// 模型类型 + /// 属性类型 + public class ModelSelect : Select { + /// + /// 初始化模型下拉列表 + /// + /// 属性表达式 + public ModelSelect( Expression> expression ) { + if( expression == null ) + return; + _expression = expression; + _memberInfo = Lambda.GetMember( _expression ); + Init(); + } + + /// + /// 属性表达式 + /// + private readonly Expression> _expression; + /// + /// 成员 + /// + private readonly MemberInfo _memberInfo; + + /// + /// 初始化 + /// + private void Init() { + InitModel(); + InitPlaceholder(); + InitType(); + InitRequired(); + } + + /// + /// 初始化模型绑定 + /// + private void InitModel() { + var model = Helper.GetModel( _expression ); + if ( string.IsNullOrWhiteSpace( model ) ) + return; + this.Model( model ); + } + + /// + /// 初始化占位提示符 + /// + private void InitPlaceholder() { + this.Placeholder( Reflection.GetDisplayNameOrDescription( _memberInfo ) ); + } + + /// + /// 根据类型初始化 + /// + private void InitType() { + if( Reflection.IsBool( _memberInfo ) ) + this.Bool(); + else if( Reflection.IsEnum( _memberInfo ) ) + Enum(); + } + + /// + /// 初始化必填项验证 + /// + private void InitRequired() { + var attribute = Lambda.GetAttribute( _expression ); + if( attribute != null ) + this.Required( attribute.ErrorMessage ); + } + } +} diff --git a/src/Util.Ui.Angular/Material/Forms/Renders/SelectRender.cs b/src/Util.Ui.Angular/Material/Forms/Renders/SelectRender.cs index 3e66dc9a..1f404ce5 100644 --- a/src/Util.Ui.Angular/Material/Forms/Renders/SelectRender.cs +++ b/src/Util.Ui.Angular/Material/Forms/Renders/SelectRender.cs @@ -91,7 +91,7 @@ namespace Util.Ui.Material.Forms.Renders { /// 配置模型绑定 /// private void ConfigModel( SelectWrapperBuilder builder ) { - builder.AddAttribute( "[(model)]", _config.GetBoolValue( UiConst.Model ) ); + builder.AddAttribute( "[(model)]", _config.GetValue( UiConst.Model ) ); } /// diff --git a/src/Util.Ui.Angular/Material/Services/IUiService.cs b/src/Util.Ui.Angular/Material/Services/IUiService.cs new file mode 100644 index 00000000..72051e7a --- /dev/null +++ b/src/Util.Ui.Angular/Material/Services/IUiService.cs @@ -0,0 +1,17 @@ +using System; +using System.Linq.Expressions; +using Util.Ui.Components; + +namespace Util.Ui.Material.Services { + /// + /// 组件服务 + /// + public interface IUiService { + /// + /// 下拉列表 + /// + /// 属性类型 + /// 属性表达式 + ISelect Select( Expression> expression ); + } +} diff --git a/src/Util.Ui.Angular/Material/Services/UiService.cs b/src/Util.Ui.Angular/Material/Services/UiService.cs new file mode 100644 index 00000000..b83a968d --- /dev/null +++ b/src/Util.Ui.Angular/Material/Services/UiService.cs @@ -0,0 +1,32 @@ +using System; +using System.Linq.Expressions; +using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Mvc.Rendering; +using Util.Ui.Components; +using Util.Ui.Material.Forms.Models; +using Util.Ui.Services; + +namespace Util.Ui.Material.Services { + /// + /// 组件服务 + /// + /// 模型类型 + public class UiService : UiServiceBase, IUiService { + /// + /// 初始化组件服务 + /// + /// HtmlHelper + /// Html编码 + public UiService( IHtmlHelper helper, HtmlEncoder encoder ) : base( helper, encoder ) { + } + + /// + /// 下拉列表 + /// + /// 属性类型 + /// 属性表达式 + public ISelect Select( Expression> expression ) { + return new ModelSelect( expression ); + } + } +} diff --git a/src/Util.Ui.Core/Attributes/ModelAttribute.cs b/src/Util.Ui.Core/Attributes/ModelAttribute.cs new file mode 100644 index 00000000..782e3a0b --- /dev/null +++ b/src/Util.Ui.Core/Attributes/ModelAttribute.cs @@ -0,0 +1,27 @@ +using System; + +namespace Util.Ui.Attributes { + /// + /// 模型绑定 + /// + [AttributeUsage( AttributeTargets.Class | AttributeTargets.Property )] + public class ModelAttribute : Attribute { + /// + /// 初始化模型绑定 + /// + /// 模型 + public ModelAttribute( string model = "" ) { + Model = model; + } + + /// + /// 模型 + /// + public string Model { get; set; } + + /// + /// 忽略模型绑定,设置为true则不设置模型绑定 + /// + public bool Ignore { get; set; } + } +} diff --git a/src/Util.Ui.Core/Extensions/Extensions.Component.Form.cs b/src/Util.Ui.Core/Extensions/Extensions.Component.Form.cs index 11952563..f1eb9dd6 100644 --- a/src/Util.Ui.Core/Extensions/Extensions.Component.Form.cs +++ b/src/Util.Ui.Core/Extensions/Extensions.Component.Form.cs @@ -9,7 +9,7 @@ namespace Util.Ui.Extensions { /// public static partial class Extensions { /// - /// 设置占位符 + /// 设置占位提示符 /// /// 组件类型 /// 组件实例 diff --git a/src/Util.Ui.Core/Internal/Helper.cs b/src/Util.Ui.Core/Internal/Helper.cs new file mode 100644 index 00000000..9b462d79 --- /dev/null +++ b/src/Util.Ui.Core/Internal/Helper.cs @@ -0,0 +1,44 @@ +using System; +using System.Linq.Expressions; +using System.Reflection; +using Util.Helpers; +using Util.Ui.Attributes; + +namespace Util.Ui.Internal { + /// + /// 辅助操作 + /// + public static class Helper { + /// + /// 获取模型 + /// + /// 模型类型 + /// 属性类型 + public static string GetModel( Expression> expression ) { + var modelName = Util.Helpers.String.FirstLowerCase( GetModelName() ); + var propertyName = Util.Helpers.String.FirstLowerCase( GetPropertyName( expression ) ); + if ( string.IsNullOrWhiteSpace( modelName ) || string.IsNullOrWhiteSpace( propertyName ) ) + return string.Empty; + return $"{modelName}.{propertyName}"; + } + + /// + /// 获取模型名称 + /// + private static string GetModelName() { + Type type = Common.GetType(); + if ( type.GetCustomAttribute() is ModelAttribute attribute ) { + return attribute.Ignore ? string.Empty : attribute.Model; + } + return typeof( TModel ).Name; + } + + /// + /// 获取属性名称 + /// + private static string GetPropertyName( Expression> expression ) { + var attribute = Lambda.GetAttribute( expression ); + return attribute == null ? Lambda.GetName( expression ) : attribute.Ignore ? string.Empty : attribute.Model; ; + } + } +} diff --git a/src/Util.Ui.Core/Services/UiService.cs b/src/Util.Ui.Core/Services/UiServiceBase.cs similarity index 75% rename from src/Util.Ui.Core/Services/UiService.cs rename to src/Util.Ui.Core/Services/UiServiceBase.cs index 05c6b1e8..44ee2a69 100644 --- a/src/Util.Ui.Core/Services/UiService.cs +++ b/src/Util.Ui.Core/Services/UiServiceBase.cs @@ -5,13 +5,13 @@ namespace Util.Ui.Services { /// /// 组件服务 /// - public class UiService : IUiService, IContext { + public class UiServiceBase : IContext { /// /// 初始化组件服务 /// /// HtmlHelper /// Html编码 - public UiService( IHtmlHelper helper, HtmlEncoder encoder) { + public UiServiceBase( IHtmlHelper helper, HtmlEncoder encoder ) { Helper = helper; Encoder = encoder; } @@ -19,7 +19,7 @@ namespace Util.Ui.Services { /// /// HtmlHelper /// - public IHtmlHelper Helper { get; } + public IHtmlHelper Helper { get; } /// /// Html编码 diff --git a/src/Util/Helpers/Reflection.cs b/src/Util/Helpers/Reflection.cs index 3c9e7be7..09180299 100644 --- a/src/Util/Helpers/Reflection.cs +++ b/src/Util/Helpers/Reflection.cs @@ -81,7 +81,7 @@ namespace Util.Helpers { /// /// 获取属性显示名称或描述,使用DisplayNameAttribute或DisplayAttribute设置显示名称,使用DescriptionAttribute设置描述 /// - public static string GetDisplayNameOrDescription( PropertyInfo member ) { + public static string GetDisplayNameOrDescription( MemberInfo member ) { var result = GetDisplayName( member ); return string.IsNullOrWhiteSpace( result ) ? GetDescription( member ) : result; } @@ -89,7 +89,7 @@ namespace Util.Helpers { /// /// 获取类型成员显示名称,使用DisplayNameAttribute或DisplayAttribute设置显示名称 /// - private static string GetDisplayName( PropertyInfo member ) { + private static string GetDisplayName( MemberInfo member ) { if( member == null ) return string.Empty; if( member.GetCustomAttribute( typeof( DisplayNameAttribute ) ) is DisplayNameAttribute displayNameAttribute ) @@ -147,11 +147,7 @@ namespace Util.Helpers { /// 是否布尔类型 /// private static bool IsBool( PropertyInfo property ) { - if( property.PropertyType == typeof( bool ) ) - return true; - if( property.PropertyType == typeof( bool? ) ) - return true; - return false; + return property.PropertyType == typeof( bool ) || property.PropertyType == typeof( bool? ); } /// diff --git a/src/Util/Helpers/String.Tools.cs b/src/Util/Helpers/String.Tools.cs index 9224cce4..a25c17bb 100644 --- a/src/Util/Helpers/String.Tools.cs +++ b/src/Util/Helpers/String.Tools.cs @@ -123,5 +123,19 @@ namespace Util.Helpers { } #endregion + + #region FirstLowerCase(首字母小写) + + /// + /// 首字母小写 + /// + /// 值 + public static string FirstLowerCase( string value ) { + if ( string.IsNullOrWhiteSpace( value ) ) + return string.Empty; + return $"{value.Substring( 0, 1 ).ToLower()}{value.Substring( 1 )}"; + } + + #endregion } } diff --git a/test/Util.Tests/Helpers/StringTest.Tools.cs b/test/Util.Tests/Helpers/StringTest.Tools.cs index d7bd4e7f..bd67b692 100644 --- a/test/Util.Tests/Helpers/StringTest.Tools.cs +++ b/test/Util.Tests/Helpers/StringTest.Tools.cs @@ -25,8 +25,8 @@ namespace Util.Tests.Helpers { new Guid( "83B0233C-A24F-49FD-8083-1337209EBC9A" ), new Guid( "EAB523C6-2FE7-47BE-89D5-C6D440C3033A" ) }; - Assert.Equal( "83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A".ToLower(),Util.Helpers.String.Join( list ) ); - Assert.Equal( "'83B0233C-A24F-49FD-8083-1337209EBC9A','EAB523C6-2FE7-47BE-89D5-C6D440C3033A'".ToLower(),Util.Helpers.String.Join( list, "'" ) ); + Assert.Equal( "83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A".ToLower(), Util.Helpers.String.Join( list ) ); + Assert.Equal( "'83B0233C-A24F-49FD-8083-1337209EBC9A','EAB523C6-2FE7-47BE-89D5-C6D440C3033A'".ToLower(), Util.Helpers.String.Join( list, "'" ) ); } /// @@ -42,5 +42,21 @@ namespace Util.Tests.Helpers { public void TestPinYin( string input, string result ) { Assert.Equal( result, Util.Helpers.String.PinYin( input ) ); } + + /// + /// 首字母小写 + /// + [Theory] + [InlineData( null, "" )] + [InlineData( "", "" )] + [InlineData( " ", "" )] + [InlineData( "a", "a" )] + [InlineData( "A", "a" )] + [InlineData( "Ab", "ab" )] + [InlineData( "AB", "aB" )] + [InlineData( "Abc", "abc" )] + public void TestFirstLowerCase( string value, string result ) { + Assert.Equal( result, Util.Helpers.String.FirstLowerCase( value ) ); + } } } diff --git a/test/Util.Ui.Tests/Material/Forms/TextBoxTest.cs b/test/Util.Ui.Tests/Material/Forms/TextBoxTest.cs index 1808e2a3..5a0e9d73 100644 --- a/test/Util.Ui.Tests/Material/Forms/TextBoxTest.cs +++ b/test/Util.Ui.Tests/Material/Forms/TextBoxTest.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text.Encodings.Web; using Util.Helpers; using Util.Ui.Extensions; +using Util.Ui.Material.Extensions; using Util.Ui.Material.Forms; using Util.Webs; using Xunit;