解决FullCalendar在WebForm回发后视图重置的问题
WebForm中FullCalendar回发后视图日期偏移问题
问题背景
在WebForm页面使用FullCalendar,终端用户使用正常,但管理员添加/编辑事件时触发回发,日历视图会重置为默认状态,给需要提前一年甚至更久添加事件的操作带来困扰。
已尝试的解决方案
- 添加隐藏的
TextBox存储日历视图的起始日期:
<asp:TextBox ID="txtSaveTheDate" style="display:none;" runat="server"></asp:TextBox>
- 在触发事件(点击事件/日期)时,更新文本框值为当前视图的起始日期:
eventClick: function (calEvent, jsEvent, view) { document.getElementById('<%=txtSaveTheDate.ClientID%>').value = view.start.format(); // 其他逻辑... },
- 页面回发后,通过FullCalendar的
defaultDate属性读取存储的日期,恢复视图:
defaultDate: moment(SaveTheDate),
现存问题
上述方案仅部分有效:点击创建事件时,正确的日期会存入文本框,但页面回发后,日历会跳转到应显示月份的前一个月,无论当前是过去、现在还是未来的月份。仅2023年1月能正常显示,该月份的特殊之处在于视图从当月1日开始,与其他月份不同。
完整实现代码
jQuery(document).ready(function () { SaveTheDate = document.getElementById('<%=txtSaveTheDate.ClientID%>').value; if (SaveTheDate == '') { SaveTheDate = new Date(); }; $.ajax({ type: "POST", contentType: "application/json", data: "{}", url: "TrainingCalendar.aspx/GetEvents", dataType: "json", success: function (data) { $('div[id*=fullcal]').fullCalendar({ header: { left: 'prev,next today', center: 'title', right: 'month' }, defaultDate: moment(SaveTheDate), displayEventTime: false, events: $.map(data.d, function (item, i) { var event = new Object(); event.id = item.EventID event.start = new Date(item.StartDate); event.end = new Date(item.EndDate); event.title = item.EventName; event.backgroundColor = item.Color; event.textColor = item.TextColor; return event; }), eventClick: function (calEvent, jsEvent, view) { // 验证编辑权限 if (document.getElementById('<%=btnNotes.ClientID%>')) { document.getElementById('<%=txtSaveTheDate.ClientID%>').value = view.start.format(); document.getElementById('<%=txtEventId.ClientID%>').value = calEvent.id; document.getElementById('<%=txtEventName.ClientID%>').value = calEvent.title; var date = new Date(calEvent.start); document.getElementById('<%=txtDate.ClientID%>').value = ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear(); $('#EventModal').modal('show'); } }, dayClick: function (dt, jsEvent, view) { // 验证编辑权限 if (document.getElementById('<%=btnNotes.ClientID%>')) { document.getElementById('<%=txtSaveTheDate.ClientID%>').value = view.start.format(); document.getElementById('<%=ddlNewEventName.ClientID%>').value = '0'; document.getElementById('<%=txtNewEventName.ClientID%>').value = ''; document.getElementById('<%=txtNewDate.ClientID%>').value = dt.format('MM/DD/YYYY'); $('#NewEventModal').modal('show'); } } }); $("div[id=loading]").hide(); $("div[id=fullcal]").show(); }, error: function (XMLHttpRequest, textStatus, errorThrown) { debugger; } }); });
解决建议
1. 统一日期格式化规则
问题根源是view.start.format()的输出格式与moment(SaveTheDate)的解析逻辑不匹配,导致日期识别偏差:
- 存储日期时,明确指定格式,避免环境差异:
view.start.format('YYYY-MM-DD') - 初始化解析时,同步指定格式:
moment(SaveTheDate, 'YYYY-MM-DD')
2. 存储视图的当前月份而非视图起始日期
月份视图中,view.start可能是上月末的日期(比如周日起始的日历,当月1日是周日的话,视图起始为上月最后一个周日),而defaultDate是用来定位视图的基准,不是直接设置视图起始。可以:
- 存储当前视图的月份:
view.currentStart.format('YYYY-MM') - 初始化时定位到当月起始:
defaultDate: moment(SaveTheDate).startOf('month')
3. 使用局部刷新避免回发重置
将事件编辑相关的控件(模态框、按钮)放入UpdatePanel中,仅局部刷新事件数据,不重新渲染整个日历,从根源解决视图重置问题。
4. 验证服务器端日期值
回发后检查txtSaveTheDate的服务器端值是否正确,确认没有因WebForm视图状态或日期格式转换导致的数据偏差。
内容的提问来源于stack exchange,提问作者SoundWaves
相关产品推荐
相关产品推荐

