现在我制作多选日历,使用blazor。
我想在更改日期后得到回拨。
这是我的日历组件源。
<div class="table-responsive-sm">
<table class="table table-sm text-center calendar">
<thead>
<tr>
<th colspan="7">
<button @onclick="(e=> ChangeMonth(-1))" class="btn btn-link">
<
</button>
@($"{CurrentMonth:yyyy.MM}")
<button @onclick="(e=> ChangeMonth(1))" class="btn btn-link">
>
</button>
</th>
</tr>
<tr>
<th scope="col">SUN</th>
<th scope="col">MON</th>
<th scope="col">TUS</th>
<th scope="col">WED</th>
<th scope="col">THU</th>
<th scope="col">FRI</th>
<th scope="col">SAT</th>
</tr>
</thead>
<tbody>
@{
var i = 0;
var prevLastDay = CurrentMonth.AddDays(-1).Day;
}
@for (var row = 0; row < 5; row++)
{
<tr>
@for (var col = 0; col < 7; col++)
{
if (i < (int)StartDayOfWeek)
{
<td style="color:gray;">
@(prevLastDay - ((int)StartDayOfWeek - i))
</td>
}
else if (i >= (DaysInMonth + (int)StartDayOfWeek))
{
<td style="color:gray;">@(i - (DaysInMonth + (int)StartDayOfWeek) + 1)</td>
}
else
{
var day = i - (int)StartDayOfWeek + 1;
<td>
<button class="btn btn-sm btn-block @(DayClass(day))" @onclick="(e=> ToggleDate(day))">
@(day)
</button>
</td>
}
i++;
}
</tr>
}
</tbody>
</table>
</div>
@code {
/// <summary>
/// Current Month
/// </summary>
[Parameter]
public DateTime CurrentMonth { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
/// <summary>
/// Start Day Of First Day In Current Month
///</summary>
private DayOfWeek StartDayOfWeek => CurrentMonth.DayOfWeek;
/// <summary>
/// Selected Day List
/// </summary>
[Parameter]
public List<DateTime> SelectedDays { get; set; } = new List<DateTime>();
[Parameter]
public EventCallback<List<DateTime>> SelectedDaysChanged { get; set; }
/// <summary>
/// Selectable Day List
/// </summary>
[Parameter]
public List<DateTime> SelectableDays { get; set; } = new List<DateTime>();
[Parameter]
public EventCallback<DateTime> CurrentMonthChanged { get; set; }
private int DaysInMonth => DateTime.DaysInMonth(CurrentMonth.Year, CurrentMonth.Month);
protected override void OnParametersSet()
{
base.OnParametersSet();
CurrentMonth = CurrentMonth.AddDays(CurrentMonth.Day * -1 + 1);
}
protected override void OnInitialized()
{
}
public bool IsSelectable(DateTime date)
{
return SelectableDays.Select(p => p.Date).Contains(date.Date);
}
public string DayClass(int day)
{
var targetDay = new DateTime(CurrentMonth.Year, CurrentMonth.Month, day);
if (SelectedDays.Contains(targetDay))
{
return "btn-primary";
}
else if (SelectableDays.Select(p => p.Date).Contains(targetDay.Date))
{
return "btn-outline-primary";
}
return string.Empty;
}
public void ToggleDate(int day)
{
var clickedDate = new DateTime(CurrentMonth.Year, CurrentMonth.Month, day);
if (IsSelectable(clickedDate) == false)
return;
if (SelectedDays.Contains(clickedDate))
{
SelectedDays.Remove(clickedDate);
}
else
{
SelectedDays.Add(clickedDate);
}
SelectedDaysChanged.InvokeAsync(SelectedDays);
}
public void ChangeMonth(int addMonths)
{
CurrentMonth = CurrentMonth.AddMonths(addMonths);
CurrentMonthChanged.InvokeAsync(CurrentMonth);
}
}
和。我的父页面是这样使用的。
第一个
<Calendar SelectableDays="SelectableDays"
@bind-SelectedDays="SelectedDays"
SelectedDaysChanged="SelectedDaysChanged"
></Calendar>
@code{
public List<DateTime> SelectableDays { get; set; } = new List<DateTime>() { new DateTime(2020, 04, 03) };
public List<DateTime> SelectedDays { get; set; } = new List<DateTime>();
public int SelectListCount { get; set; }
public void SelectedDaysChanged(List<DateTime> selectList)
{
SelectListCount = selectList.Count;
}
}
我收到了这个消息。组件参数"SelectedDaysChanged"已为此组件使用两次或两次以上。参数必须唯一(不区分大小写(。组件参数"SelectedDaysChanged"由"@bind SelectedDays"指令属性生成。
所以我改变了我的方法。像这样。
<Calendar SelectableDays="SelectableDays"
@bind-SelectedDays="SelectedDays"></Calendar>
@code{
public List<DateTime> SelectableDays { get; set; } = new List<DateTime>() { new DateTime(2020, 04, 03) };
public List<DateTime> _selectedDays = new List<DateTime>();
public List<DateTime> SelectedDays
{
get { return _selectedDays; }
set
{
if (_selectedDays != value)
_selectedDays = value;
SelectListCount = _selectedDays.Count;
}
}
public int SelectListCount { get; set; }
}
这看起来像我想要的。
但在SelectedDays的Setter中。
if (_selectedDays != value)
总是错误的。
this mean _selectedDays set before to this setter。
问题出在哪里?
如何获取SelectedDays更改的回调事件?
我必须做其他财产?比如OnChangedSelectedDays,并调用Calendar组件的ToggleDate方法?
这是我的完整源代码。
index剃刀
@page "/"
<Calendar SelectableDays="SelectableDays"
@bind-SelectedDays="SelectedDays"></Calendar>
@code{
public List<DateTime> SelectableDays { get; set; } = new List<DateTime>() { new DateTime(2020, 04, 03) };
public List<DateTime> _selectedDays = new List<DateTime>();
[Parameter]
public List<DateTime> SelectedDays
{
get { return _selectedDays; }
set
{
if (_selectedDays != value)
_selectedDays = value;
SelectListCount = _selectedDays.Count;
}
}
public int SelectListCount { get; set; }
}
日历.razor
<div class="table-responsive-sm">
<table class="table table-sm text-center calendar">
<thead>
<tr>
<th colspan="7">
<button @onclick="(e=> ChangeMonth(-1))" class="btn btn-link">
<
</button>
@($"{CurrentMonth:yyyy.MM}")
<button @onclick="(e=> ChangeMonth(1))" class="btn btn-link">
>
</button>
</th>
</tr>
<tr>
<th scope="col">SUN</th>
<th scope="col">MON</th>
<th scope="col">TUS</th>
<th scope="col">WED</th>
<th scope="col">THU</th>
<th scope="col">FRI</th>
<th scope="col">SAT</th>
</tr>
</thead>
<tbody>
@{
var i = 0;
var prevLastDay = CurrentMonth.AddDays(-1).Day;
}
@for (var row = 0; row < 5; row++)
{
<tr>
@for (var col = 0; col < 7; col++)
{
if (i < (int)StartDayOfWeek)
{
<td style="color:gray;">
@(prevLastDay - ((int)StartDayOfWeek - i))
</td>
}
else if (i >= (DaysInMonth + (int)StartDayOfWeek))
{
<td style="color:gray;">@(i - (DaysInMonth + (int)StartDayOfWeek) + 1)</td>
}
else
{
var day = i - (int)StartDayOfWeek + 1;
<td>
<button class="btn btn-sm btn-block @(DayClass(day))" @onclick="(e=> ToggleDate(day))">
@(day)
</button>
</td>
}
i++;
}
</tr>
}
</tbody>
</table>
</div>
@code {
/// <summary>
/// Current Month
/// </summary>
[Parameter]
public DateTime CurrentMonth { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
/// <summary>
/// Start Day Of First Day In Current Month
///</summary>
private DayOfWeek StartDayOfWeek => CurrentMonth.DayOfWeek;
// I've changed the SelectedDays property in the Calendar component
// This is a parameter property, and it leads to subtle errors
// when used in your code as a local variable. Instead, define a
// local variable to get and set values from it, as I do in the
// ToggleDate method below.
private List<DateTime> _selectedDays = new List<DateTime>();
[Parameter]
public List<DateTime> SelectedDays
{
get { return _selectedDays; }
set
{
if (_selectedDays != value)
_selectedDays = value;
if (SelectedDaysChanged.HasDelegate)
{
SelectedDaysChanged.InvokeAsync(value);
}
}
}
///// <summary>
///// Selected Day List
///// </summary>
//[Parameter]
//public List<DateTime> SelectedDays { get; set; } = new List<DateTime>();
[Parameter]
public EventCallback<List<DateTime>> SelectedDaysChanged { get; set; }
/// <summary>
/// Selectable Day List
/// </summary>
[Parameter]
public List<DateTime> SelectableDays { get; set; } = new List<DateTime>();
[Parameter]
public EventCallback<DateTime> CurrentMonthChanged { get; set; }
private int DaysInMonth => DateTime.DaysInMonth(CurrentMonth.Year, CurrentMonth.Month);
protected override void OnParametersSet()
{
base.OnParametersSet();
CurrentMonth = CurrentMonth.AddDays(CurrentMonth.Day * -1 + 1);
}
protected override void OnInitialized()
{
}
public bool IsSelectable(DateTime date)
{
return SelectableDays.Select(p => p.Date).Contains(date.Date);
}
public string DayClass(int day)
{
var targetDay = new DateTime(CurrentMonth.Year, CurrentMonth.Month, day);
if (SelectedDays.Contains(targetDay))
{
return "btn-primary";
}
else if (SelectableDays.Select(p => p.Date).Contains(targetDay.Date))
{
return "btn-outline-primary";
}
return string.Empty;
}
public void ToggleDate(int day)
{
var clickedDate = new DateTime(CurrentMonth.Year,
CurrentMonth.Month, day);
if (IsSelectable(clickedDate) == false)
return;
var selectedDays = SelectedDays;
if (selectedDays.Contains(clickedDate))
{
selectedDays.Remove(clickedDate);
}
else
{
selectedDays.Add(clickedDate);
}
// Update the SelectedDays property
SelectedDays = selectedDays;
//var clickedDate = new DateTime(CurrentMonth.Year, CurrentMonth.Month, day);
//if (IsSelectable(clickedDate) == false)
// return;
//if (SelectedDays.Contains(clickedDate))
//{
// SelectedDays.Remove(clickedDate);
//}
//else
//{
// SelectedDays.Add(clickedDate);
//}
//SelectedDaysChanged.InvokeAsync(SelectedDays);
}
public void ChangeMonth(int addMonths)
{
CurrentMonth = CurrentMonth.AddMonths(addMonths);
CurrentMonthChanged.InvokeAsync(CurrentMonth);
}
}
完整的来源。
index剃刀
@page "/"
<Calendar SelectableDays="SelectableDays"
@bind-SelectedDays="SelectedDays"></Calendar>
<div>
@SelectListCount
</div>
@code{
public List<DateTime> SelectableDays { get; set; } = new List<DateTime>() { new DateTime(2020, 04, 03) };
public List<DateTime> _selectedDays = new List<DateTime>();
[Parameter]
public List<DateTime> SelectedDays
{
get { return _selectedDays; }
set
{
if (_selectedDays != value)
_selectedDays = value;
SelectListCount = _selectedDays.Count;
}
}
public int SelectListCount { get; set; }
}
日历.razor
<div class="table-responsive-sm">
<table class="table table-sm text-center calendar">
<thead>
<tr>
<th colspan="7">
<button @onclick="(e=> ChangeMonth(-1))" class="btn btn-link">
<
</button>
@($"{CurrentMonth:yyyy.MM}")
<button @onclick="(e=> ChangeMonth(1))" class="btn btn-link">
>
</button>
</th>
</tr>
<tr>
<th scope="col">SUN</th>
<th scope="col">MON</th>
<th scope="col">TUS</th>
<th scope="col">WED</th>
<th scope="col">THU</th>
<th scope="col">FRI</th>
<th scope="col">SAT</th>
</tr>
</thead>
<tbody>
@{
var i = 0;
var prevLastDay = CurrentMonth.AddDays(-1).Day;
}
@for (var row = 0; row < 5; row++)
{
<tr>
@for (var col = 0; col < 7; col++)
{
if (i < (int)StartDayOfWeek)
{
<td style="color:gray;">
@(prevLastDay - ((int)StartDayOfWeek - i))
</td>
}
else if (i >= (DaysInMonth + (int)StartDayOfWeek))
{
<td style="color:gray;">@(i - (DaysInMonth + (int)StartDayOfWeek) + 1)</td>
}
else
{
var day = i - (int)StartDayOfWeek + 1;
<td>
<button class="btn btn-sm btn-block @(DayClass(day))" @onclick="@((e) => ToggleDate(day))">
@(day)
</button>
</td>
}
i++;
}
</tr>
}
</tbody>
</table>
</div>
@code {
/// <summary>
/// Current Month
/// </summary>
[Parameter]
public DateTime CurrentMonth { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
/// <summary>
/// Start Day Of First Day In Current Month
///</summary>
private DayOfWeek StartDayOfWeek => CurrentMonth.DayOfWeek;
[Parameter]
public List<DateTime> SelectedDays { get; set; }
///// <summary>
///// Selected Day List
///// </summary>
//[Parameter]
//public List<DateTime> SelectedDays { get; set; } = new List<DateTime>();
[Parameter]
public EventCallback<List<DateTime>> SelectedDaysChanged { get; set; }
/// <summary>
/// Selectable Day List
/// </summary>
[Parameter]
public List<DateTime> SelectableDays { get; set; }
[Parameter]
public EventCallback<DateTime> CurrentMonthChanged { get; set; }
private int DaysInMonth => DateTime.DaysInMonth(CurrentMonth.Year, CurrentMonth.Month);
protected override void OnParametersSet()
{
base.OnParametersSet();
CurrentMonth = CurrentMonth.AddDays(CurrentMonth.Day * -1 + 1);
}
protected override void OnInitialized()
{
}
public bool IsSelectable(DateTime date)
{
return SelectableDays.Select(p => p.Date).Contains(date.Date);
}
public string DayClass(int day)
{
var targetDay = new DateTime(CurrentMonth.Year, CurrentMonth.Month, day);
if (SelectedDays.Contains(targetDay))
{
return "btn-primary";
}
else if (SelectableDays.Select(p => p.Date).Contains(targetDay.Date))
{
return "btn-outline-primary";
}
return string.Empty;
}
public void ToggleDate(int day)
{
var clickedDate = new DateTime(CurrentMonth.Year,
CurrentMonth.Month, day);
//if (IsSelectable(clickedDate) == false)
// return;
var tempSelectedDays = SelectedDays.Select(p => p).ToList(); // add here
if (tempSelectedDays.Contains(clickedDate))
{
tempSelectedDays.Remove(clickedDate);
}
else
{
tempSelectedDays.Add(clickedDate);
}
SelectedDaysChanged.InvokeAsync(tempSelectedDays);
}
public void ChangeMonth(int addMonths)
{
CurrentMonth = CurrentMonth.AddMonths(addMonths);
CurrentMonthChanged.InvokeAsync(CurrentMonth);
}
}
好吧,这就是罪魁祸首:
//if (IsSelectable(clickedDate) == false)
// return;
以下代码正在工作:
索引.razor
@page "/"
<Calendar SelectableDays="SelectableDays"
@bind-SelectedDays="@SelectedDays"></Calendar>
@code{
public List<DateTime> SelectableDays { get; set; } = new
List<DateTime>() { new DateTime(2020, 04, 03) };
private List<DateTime> _selectedDays = new List<DateTime>();
[Parameter]
public List<DateTime> SelectedDays
{
get { return _selectedDays; }
set
{
if (_selectedDays != value)
_selectedDays = value;
SelectListCount = _selectedDays.Count;
}
}
public int SelectListCount { get; set; }
}
日历.razor
<div class="table-responsive-sm">
<table class="table table-sm text-center calendar">
<thead>
<tr>
<th colspan="7">
<button @onclick="(e=> ChangeMonth(-1))" class="btn btn-link">
<
</button>
@($"{CurrentMonth:yyyy.MM}")
<button @onclick="(e=> ChangeMonth(1))" class="btn btn-link">
>
</button>
</th>
</tr>
<tr>
<th scope="col">SUN</th>
<th scope="col">MON</th>
<th scope="col">TUS</th>
<th scope="col">WED</th>
<th scope="col">THU</th>
<th scope="col">FRI</th>
<th scope="col">SAT</th>
</tr>
</thead>
<tbody>
@{
var i = 0;
var prevLastDay = CurrentMonth.AddDays(-1).Day;
}
@for (var row = 0; row < 5; row++)
{
<tr>
@for (var col = 0; col < 7; col++)
{
if (i < (int)StartDayOfWeek)
{
<td style="color:gray;">
@(prevLastDay - ((int)StartDayOfWeek - i))
</td>
}
else if (i >= (DaysInMonth + (int)StartDayOfWeek))
{
<td style="color:gray;">@(i - (DaysInMonth + (int)StartDayOfWeek) + 1)</td>
}
else
{
var day = i - (int)StartDayOfWeek + 1;
<td>
<button class="btn btn-sm btn-block @(DayClass(day))" @onclick="@((e) => ToggleDate(day))">
@(day)
</button>
</td>
}
i++;
}
</tr>
}
</tbody>
</table>
</div>
@code {
/// <summary>
/// Current Month
/// </summary>
[Parameter]
public DateTime CurrentMonth { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
/// <summary>
/// Start Day Of First Day In Current Month
///</summary>
private DayOfWeek StartDayOfWeek => CurrentMonth.DayOfWeek;
[Parameter]
public List<DateTime> SelectedDays { get; set; }
///// <summary>
///// Selected Day List
///// </summary>
//[Parameter]
//public List<DateTime> SelectedDays { get; set; } = new List<DateTime>();
[Parameter]
public EventCallback<List<DateTime>> SelectedDaysChanged { get; set; }
/// <summary>
/// Selectable Day List
/// </summary>
[Parameter]
public List<DateTime> SelectableDays { get; set; }
[Parameter]
public EventCallback<DateTime> CurrentMonthChanged { get; set; }
private int DaysInMonth => DateTime.DaysInMonth(CurrentMonth.Year, CurrentMonth.Month);
protected override void OnParametersSet()
{
base.OnParametersSet();
CurrentMonth = CurrentMonth.AddDays(CurrentMonth.Day * -1 + 1);
}
protected override void OnInitialized()
{
}
public bool IsSelectable(DateTime date)
{
return SelectableDays.Select(p => p.Date).Contains(date.Date);
}
public string DayClass(int day)
{
var targetDay = new DateTime(CurrentMonth.Year, CurrentMonth.Month, day);
if (SelectedDays.Contains(targetDay))
{
return "btn-primary";
}
else if (SelectableDays.Select(p => p.Date).Contains(targetDay.Date))
{
return "btn-outline-primary";
}
return string.Empty;
}
public void ToggleDate(int day)
{
var clickedDate = new DateTime(CurrentMonth.Year,
CurrentMonth.Month, day);
//if (IsSelectable(clickedDate) == false)
// return;
Console.WriteLine($"ToggleDate {day}");
if (SelectedDays.Contains(clickedDate))
{
SelectedDays.Remove(clickedDate);
}
else
{
SelectedDays.Add(clickedDate);
}
SelectedDaysChanged.InvokeAsync(SelectedDays);
}
public void ChangeMonth(int addMonths)
{
CurrentMonth = CurrentMonth.AddMonths(addMonths);
CurrentMonthChanged.InvokeAsync(CurrentMonth);
}
}
不错的日历,当你在这里张贴完代码;(
希望这能有所帮助。。