【问题标题】:blazor can use custom property changed callback event?blazor 可以使用自定义属性更改回调事件吗?
【发布时间】:2020-04-03 07:00:02
【问题描述】:

现在我制作多选日历,使用 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">
                        &lt;
                    </button>
                    @($"{CurrentMonth:yyyy.MM}")
                    <button @onclick="(e=> ChangeMonth(1))" class="btn btn-link">
                        &gt;
                    </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)

总是假的。

这意味着 _selectedDays 之前设置到这个 setter 中。

什么问题?

如何获取 SelectedDays 更改的回调事件?

我必须做其他财产? 像 OnChangedSelectedDays,并调用 Calendar 组件的 ToggleDate 方法?

这是我的完整源代码。

index.razor

    @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">
                        &lt;
                    </button>
                    @($"{CurrentMonth:yyyy.MM}")
                    <button @onclick="(e=> ChangeMonth(1))" class="btn btn-link">
                        &gt;
                    </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.razor

@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; }
}

calendar.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">
                        &lt;
                    </button>
                    @($"{CurrentMonth:yyyy.MM}")
                    <button @onclick="(e=> ChangeMonth(1))" class="btn btn-link">
                        &gt;
                    </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);
    }
}

【问题讨论】:

    标签: c# .net-core blazor


    【解决方案1】:

    好吧,这就是罪魁祸首:

    //if (IsSelectable(clickedDate) == false)
        //    return;
    

    以下代码正在运行:

    Index.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">
                        &lt;
                    </button>
                    @($"{CurrentMonth:yyyy.MM}")
                    <button @onclick="(e=> ChangeMonth(1))" class="btn btn-link">
                        &gt;
                    </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);
    }
    }
    

    不错的日历,当您在这里完成发布代码时;)

    希望这会有所帮助..

    【讨论】:

    • 现在我发布我的完整源代码。新答案在索引的 SelectedDays 设置器中不起作用 T.T. 无限循环..
    • 嗯,谢谢回答,我认为这不起作用,(因为 index.razor 中的 _selectedDays != value 总是 false )但我发现了一些技巧。从你的回答。感谢你!。我更新我的问题大声笑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多