使用可为空和不可为空的日期值创建 Blazor 自定义日期选择器组件
Posted
技术标签:
【中文标题】使用可为空和不可为空的日期值创建 Blazor 自定义日期选择器组件【英文标题】:Create Blazor custom date picker component with nullable and non-nullable date value 【发布时间】:2021-05-01 13:15:00 【问题描述】:我想在 Blazor 中创建自定义日期选择器组件。我的代码是这样的
<div class="form-group">
<label>@Title</label>
<input type="date" class="form-control" @bind="Value" />
</div>
@code
[Parameter]
public string Title get;set;
private DateTime? _value;
[Parameter]
public DateTime? Value
get
return _value;
set
if (Value == _value)
return;
_value = value;
ValueChanged.InvokeAsync(value);
[Parameter]
public EventCallback<DateTime?> ValueChanged get; set;
问题是该组件仅在值为可为空的 DateTime (DateTime?) 时才有效,如果值为 DateTime,则会引发错误
cannot convert from 'Microsoft.AspNetCore.Components.EventCallback<System.DateTime>' to 'Microsoft.AspNetCore.Components.EventCallback'
我决定让绑定值接受可为空的,因为我认为它会接受这两种类型。它与 int、double ... 等一起工作。 所以我想让它接受 DateTime 和 DateTime? 有什么想法吗?
更新: 我试图让组件接受泛型类型,但它会抛出错误 无法将 T 转换为 DateTime
【问题讨论】:
【参考方案1】:这里是你的泛型组件:
@using System.Globalization
@using System
@typeparam TValue
<div class="form-group">
<label>@Title</label>
<input
type="date"
class="form-control"
value="@FormatValueAsString(Value)"
@onchange="@OnChange"
/>
</div>
@code
private const string DateFormat = "yyyy-MM-dd";
CultureInfo provider = CultureInfo.InvariantCulture;
private TValue _value;
[Parameter] public string Title get; set;
[Parameter] public TValue Value
get
return _value;
set
if (EqualityComparer<TValue>.Default.Equals(value , _value))
return;
_value = value;
ValueChanged.InvokeAsync(value);
[Parameter] public EventCallback<TValue> ValueChanged get; set;
private void OnChange( ChangeEventArgs args)
try
Value =
(TValue)(object)
DateTime
.ParseExact(args.Value.ToString(),DateFormat, provider);
catch
Value = default(TValue); // not sure you want this
protected string FormatValueAsString(TValue? value)
switch (value)
case DateTime dateTimeValue:
var r = BindConverter.FormatValue(dateTimeValue, DateFormat, provider);
return r;
default:
return string.Empty;
但是……我建议你继承InputDate。
看看"Option 2 (recomended): Through inheritance from InputBase "
在https://blazorrepl.com/repl/QlYPQBFj03U9ITNe13查看我
【讨论】:
谢谢,这是我正在寻找的解决方案。我会检查建议的链接【参考方案2】:更简单的方法是继承微软的 InputDate 组件。我在 Blazor 中实现了 Bootstrap4 验证样式,请参见以下 sn-ps:
@inherits InputDate<TValue>
@typeparam TValue
<input @attributes="AdditionalAttributes"
type="date"
class="@Bs4InputHelpers.FixClassNames(CssClass)"
value="@BindConverter.FormatValue(CurrentValueAsString)"
@oninput="EventCallback.Factory.CreateBinder<string>(
this, value => CurrentValueAsString = value, CurrentValueAsString)" />
@code
对于帮助者:
public static class Bs4InputHelpers
public static string FixClassNames(string inputClassNames)
//NOTE: Notice the space in front of the class name, this is to ensure we get
// the suffix to our existing form-control class set from the mark up and NOT
// half of an invalid tag. We could use a reg-ex but that might be a bit
// too slow for the UI rendering to stay smooth.
// The invalid string shall always be fixed up, as we can never get it until the
// element has checked at least once by an attempted submit.
string result = inputClassNames.Replace(" invalid", " is-invalid");
// The valid tag is on by default, and to keep consistency with BS4 we only want
// it to appear either when our field is modified, or we've tried a submit
if (inputClassNames.Contains("modified"))
result = result.Replace(" valid", " is-valid");
return result;
【讨论】:
以上是关于使用可为空和不可为空的日期值创建 Blazor 自定义日期选择器组件的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Linq 的 where 条件下从可为空的日期时间中删除时间部分