我正在制作一个预订小房间的网络应用程序,我希望在给定的间隔内刷新网页;即给定的分钟或对数据库进行更改的时间。我找到了StateHasChanged();
,但我真的不知道如何实现(这里是Newbie One Kenobi!)
我试图将其放在向约会添加约会的功能中:
var result = Service.CreateSchedule(nextSchedule);
if (result)
{
StateHasChanged();
NavigationManager.NavigateTo("/roomzfront/1");
}
但是我可能需要更多的东西,或者在代码的其他地方。
答案 0 :(得分:6)
实际上,您无需刷新页面即可获取新版本的数据库内容。
相反,我们要做的就是从数据库中重新获取数据,因为浏览器中显示的内容已绑定到首次加载页面时获取的数据。
例如,如果您有一个页面List.razor
显示数据,那么您也可以在其中创建新的数据行。因此,您可能具有以下代码:
@page "/list"
@inject DbService DbService
<h2>All Data Lines<h2>
<table>
<thead>
<tr>
<th>Title</th>
<th>Content</th>
</tr>
</thead>
<tbody>
@foreach (var line in dataLines)
{
<tr>
<td>@line.Title</td>
<td>@line.Content</td>
</tr>
}
</tbody>
</table>
<h2>Add A New Data Line</h2>
<input type="text" placeholder="Title" @bind="newLine.Title"/>
<input type="text" placeholder="Content" @bind="newLine.Content"/>
<button @onclick="AddNewLine">Add</button>
@code
{
List<DataLine> dataLines = new List<DataLine>();
protected override void OnInitialized()
{
dataLines = DbService.GetAllData();
}
DataLine newLine = new DataLine();
void AddNewLine()
{
DbService.CreateLine(newLine);
}
}
为帮助您了解其外观,让我们在脑海中运行代码;这是您的浏览器,位于下面:
(<-) (->) (https://contoso.com/list )
|---------------------|------------------|
| Title | Content |
|=====================|==================|
| Data1 | Content1 |
|---------------------|------------------|
| Data2 | Content2 |
|---------------------|------------------|
[ Title ]
[ Content ]
(Add)
=================浏览器结尾================
现在,让我们在Title
和Content
中输入一些内容,然后单击Add
。您的网站现在开始向您的数据库提交“添加”请求。此后,直到刷新,您才能在上表中看到任何更改。这是因为在第一次加载页面时会获取表中当前显示的数据。刷新页面时,它将再次获取数据。但是,如果您不这样做,则数据已经过时,但是我们要做的就是在您的网站对数据库进行一些更改后手动更新(获取)数据。这意味着您可以像这样在函数dataLines = DbService.GetAllData();
的末尾添加一行void AddNewLine()
:
void AddNewLine()
{
DbService.CreateLine(newLine);
DbService.GetAllData();
}
现在,由于已重新获取数据,因此您的表现在正在显示数据库中的最新数据。
希望对您有所帮助,如果有任何问题,请随时告诉我!
答案 1 :(得分:2)
您需要使用SignalR或WebSockets(这些天已经受到开箱即用的支持)来获取数据库更新通知,尽管坦率地说,除非是Firebase或SapphireDb,否则实际上从数据库获取通知可能会很痛苦。
您可以使用Notifications API,但是您需要编写Javascript Interop才能与Service Worker聊天,并且这些天大多数理智的人默认情况下会关闭通知。或者我想这里有Server Push协议,但是并没有得到普遍支持,服务工作者也是这样。
关于实际的更改通知,最好的选择是将其作为成功写入数据操作的一部分在中间层触发(除非如上所述,除非是Firebase或Sapphire),但请注意,如果数据来自其他来源,只是您的WebAPI层,这是不正确的。
TL; DR-您选择了一个非常艰难的团队。听起来微不足道,尤其是对于管理类型,但这绝对不是。
答案 2 :(得分:0)
您可以在下面尝试-
<ul>
@foreach (var booking in Bookings)
{
<li>@booking.BookedRoomNumber</li>
}
</ul>
@functions{
var timer = new Timer(new TimerCallback(_ =>
{
// Code to fetch the data and bind it to the page level variable
// Ex : Bookings = GetBookingsData();
// This line is necessary
this.StateHasChanged();
}), null, 1000, 1000);
}
答案 3 :(得分:0)
如果您不想使用SignalR或WebSockets,这是另一种方法。
作为Sprite组件的一部分,我有一个按时间间隔调度的Timer,为您提供了执行该操作的示例:
Sprite具有一个名为“订户”的属性
[Parameter]
public ISpriteSubscriber { get; set; }
主机组件或页面是ISpriteSubscriber接口。
namespace DataJuggler.Blazor.Components.Interfaces
{
#region interface ISpriteSubscriber
/// <summary>
/// This interface is used by the AnimationManager to notifiy callers that a refresh occurred.
/// </summary>
public interface ISpriteSubscriber
{
#region Methods
#region Refresh()
/// <summary>
/// This method will call StateHasChanged to refresh the UI
/// </summary>
void Refresh();
#endregion
#region Register(Sprite sprite)
/// <summary>
/// This method is called by the Sprite to a subscriber so it can register with the subscriber, and
/// receiver events after that.
/// </summary>
void Register(Sprite sprite);
#endregion
#endregion
#region Properties
#region ProgressBar
/// <summary>
/// This is used so the ProgressBar is stored and available to the Subscriber after Registering
/// </summary>
ProgressBar ProgressBar { get; set; }
#endregion
#endregion
}
#endregion
}
在设置剃须刀代码中设置父项之前,请设置Subscriber = this:
注意间隔= 50。这会将计时器设置为每50毫秒刷新一次。
在我的Sprite组件的设置器中,我要做的第一件事是调用向父级注册:
[Parameter]
public ISpriteSubscriber Subscriber
{
get { return subscriber; }
set
{
// set the value
subscriber = value;
// if the value for HasSubscriber is true
if (HasSubscriber)
{
// Register with the Subscriber so they can talk to each other
Subscriber.Register(this);
}
}
}
此处的代码位于承载小精灵并在父级中注册小精灵的“索引”页面上:
public void Register(Sprite sprite)
{
// If the sprite object exists
if (NullHelper.Exists(sprite))
{
// if this is the RedCar
if (sprite.Name == "RedCar")
{
// Set the RedCar
RedCar = sprite;
}
else
{
// Set the WhiteCar
WhiteCar = sprite;
}
}
}
现在,当我单击“开始比赛”按钮时,我只启动1个计时器,即使我有两辆车,我也不想让两个计时器运行:
public void StartRace()
{
// if both cars exist
if (NullHelper.Exists(RedCar, WhiteCar))
{
// Create a new instance of a 'RandomShuffler' object.
Shuffler = new RandomShuffler(2, 12, 100, 3);
// Start the timer on the RedCar
RedCar.Start();
}
}
这是Sprite的Start方法:
public void Start()
{
this.Timer = new Timer();
this.Timer.Interval = this.interval;
this.Timer.Elapsed += Timer_Elapsed;
this.Timer.Start();
}
然后Timer_Elapsed事件,调用订阅服务器以刷新:
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
// if a subscriber exists
if (HasSubscriber)
{
// Notify Subscriber
Subscriber.Refresh();
}
}
现在,在这种情况下,我的刷新方法每50毫秒被调用一次,我将更新UI:
public void Refresh()
{
// do your updates
// Update the UI
InvokeAsync(() =>
{
StateHasChanged();
});
}
如果要查看完整的示例,请克隆该项目,并在samples文件夹中查找ProgressBarSample。
https://github.com/DataJuggler/DataJuggler.Blazor.Components
如果您想观看以下视频: https://youtu.be/frtetHgfdIo
我在某些事情上使用了这种父/子方法,效果很好,我写了一篇关于它的博客文章:Using Interfaces To Communicate Between Blazor Components
我发现这是与其他组件交谈或发送数据的好方法。