Update a property asynchronous
up vote
3
down vote
favorite
When a property of my ViewModel is updated, other property is updated asynchronous.
Todo.cshtml:
@page "/todo"
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" bind="@todo.IsDone" />
<input bind="@todo.Title" />
</li>
}
</ul>
<input placeholder="Something todo" bind="@newTodo"/>
<button onclick="@AddTodo">Add todo</button>
@functions {
IList<TodoItem> todos = new List<TodoItem>();
string newTodo;
void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}
TodoItem.cs:
public class TodoItem
{
private bool _isDone;
public string Title { get; set; }
public bool IsDone
{
get => _isDone;
set
{
_isDone = value;
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
});
}
}
}
In synchronous (without Task.Run) this work fine, but in asynchronous the UI isn't updated.
I need explain the UI to update with StateHasChanged()
:
https://github.com/aspnet/Blazor/issues/1413
But I can't call this method in TodoItem (and I don't want TodoItem know Blazor component).
Have you a solution to update the UI?
c# .net blazor
add a comment |
up vote
3
down vote
favorite
When a property of my ViewModel is updated, other property is updated asynchronous.
Todo.cshtml:
@page "/todo"
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" bind="@todo.IsDone" />
<input bind="@todo.Title" />
</li>
}
</ul>
<input placeholder="Something todo" bind="@newTodo"/>
<button onclick="@AddTodo">Add todo</button>
@functions {
IList<TodoItem> todos = new List<TodoItem>();
string newTodo;
void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}
TodoItem.cs:
public class TodoItem
{
private bool _isDone;
public string Title { get; set; }
public bool IsDone
{
get => _isDone;
set
{
_isDone = value;
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
});
}
}
}
In synchronous (without Task.Run) this work fine, but in asynchronous the UI isn't updated.
I need explain the UI to update with StateHasChanged()
:
https://github.com/aspnet/Blazor/issues/1413
But I can't call this method in TodoItem (and I don't want TodoItem know Blazor component).
Have you a solution to update the UI?
c# .net blazor
1
Why not add a callback event/handler inTodoItem
(likeIsDoneComplete
) of typeAction
that your view registers in order to callStateHasChanged
?
– Kirk Woll
Nov 18 at 19:23
Yes, I think my VM need update the view or notify the view.
– Orwel
Nov 19 at 20:47
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
When a property of my ViewModel is updated, other property is updated asynchronous.
Todo.cshtml:
@page "/todo"
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" bind="@todo.IsDone" />
<input bind="@todo.Title" />
</li>
}
</ul>
<input placeholder="Something todo" bind="@newTodo"/>
<button onclick="@AddTodo">Add todo</button>
@functions {
IList<TodoItem> todos = new List<TodoItem>();
string newTodo;
void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}
TodoItem.cs:
public class TodoItem
{
private bool _isDone;
public string Title { get; set; }
public bool IsDone
{
get => _isDone;
set
{
_isDone = value;
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
});
}
}
}
In synchronous (without Task.Run) this work fine, but in asynchronous the UI isn't updated.
I need explain the UI to update with StateHasChanged()
:
https://github.com/aspnet/Blazor/issues/1413
But I can't call this method in TodoItem (and I don't want TodoItem know Blazor component).
Have you a solution to update the UI?
c# .net blazor
When a property of my ViewModel is updated, other property is updated asynchronous.
Todo.cshtml:
@page "/todo"
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" bind="@todo.IsDone" />
<input bind="@todo.Title" />
</li>
}
</ul>
<input placeholder="Something todo" bind="@newTodo"/>
<button onclick="@AddTodo">Add todo</button>
@functions {
IList<TodoItem> todos = new List<TodoItem>();
string newTodo;
void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}
TodoItem.cs:
public class TodoItem
{
private bool _isDone;
public string Title { get; set; }
public bool IsDone
{
get => _isDone;
set
{
_isDone = value;
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
});
}
}
}
In synchronous (without Task.Run) this work fine, but in asynchronous the UI isn't updated.
I need explain the UI to update with StateHasChanged()
:
https://github.com/aspnet/Blazor/issues/1413
But I can't call this method in TodoItem (and I don't want TodoItem know Blazor component).
Have you a solution to update the UI?
c# .net blazor
c# .net blazor
edited Nov 19 at 7:45
Uwe Keim
27.4k30128210
27.4k30128210
asked Nov 18 at 18:26
Orwel
481416
481416
1
Why not add a callback event/handler inTodoItem
(likeIsDoneComplete
) of typeAction
that your view registers in order to callStateHasChanged
?
– Kirk Woll
Nov 18 at 19:23
Yes, I think my VM need update the view or notify the view.
– Orwel
Nov 19 at 20:47
add a comment |
1
Why not add a callback event/handler inTodoItem
(likeIsDoneComplete
) of typeAction
that your view registers in order to callStateHasChanged
?
– Kirk Woll
Nov 18 at 19:23
Yes, I think my VM need update the view or notify the view.
– Orwel
Nov 19 at 20:47
1
1
Why not add a callback event/handler in
TodoItem
(like IsDoneComplete
) of type Action
that your view registers in order to call StateHasChanged
?– Kirk Woll
Nov 18 at 19:23
Why not add a callback event/handler in
TodoItem
(like IsDoneComplete
) of type Action
that your view registers in order to call StateHasChanged
?– Kirk Woll
Nov 18 at 19:23
Yes, I think my VM need update the view or notify the view.
– Orwel
Nov 19 at 20:47
Yes, I think my VM need update the view or notify the view.
– Orwel
Nov 19 at 20:47
add a comment |
2 Answers
2
active
oldest
votes
up vote
3
down vote
accepted
You should do the following:
Define an action delegate in your class:
public event Action OnChange;
In this very class define a method
NotifyStateChanged()
as follows:
private void NotifyStateChanged() => OnChange?.Invoke();
This method triggers the
OnChange
event. You should call this method from your logic after fulfilling whatever task it does.
In your todo Component, add the
StateHasChanged
method to the event delegate used in yourTodoItem
class thus:
@functions
{
protected override void OnInit()
{
state.OnChange += StateHasChanged;
}
}
Hope this helps. If it does, please don't fail to accept it as the answer
add a comment |
up vote
1
down vote
Easy answer is "just fire StateHasChanged();
after modify your var":
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
StateHasChanged();
});
Because your method is async, rewrite as:
Task.Run(async () => //<--here async
{
//Simulate async work
Task.Run( async () => {
await Task.Run( () => {} ); //<--- await
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
});
//Update property
Title = Title + " - Done";
StateHasChanged();
});
To avoid anti-pattern and write clean code, your ModelView may have a public event to let know UI it has changed, just connect this event on UI to StateHasChanged();
.
I write here the Blazor Counter sample modified to do this:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" onclick="@IncrementCount">
Click me @s <!-- here var -->
</button>
@functions {
int currentCount = 0;
string s = "";
void IncrementCount()
{
currentCount++;
Task.Run(() =>
{
//Simulate work
Task.Run( async () => {
await Task.Run( () => {} );
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));}
);
//Update property
s = s + " - Done";
StateHasChanged();
});
}
}
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53364149%2fupdate-a-property-asynchronous%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
You should do the following:
Define an action delegate in your class:
public event Action OnChange;
In this very class define a method
NotifyStateChanged()
as follows:
private void NotifyStateChanged() => OnChange?.Invoke();
This method triggers the
OnChange
event. You should call this method from your logic after fulfilling whatever task it does.
In your todo Component, add the
StateHasChanged
method to the event delegate used in yourTodoItem
class thus:
@functions
{
protected override void OnInit()
{
state.OnChange += StateHasChanged;
}
}
Hope this helps. If it does, please don't fail to accept it as the answer
add a comment |
up vote
3
down vote
accepted
You should do the following:
Define an action delegate in your class:
public event Action OnChange;
In this very class define a method
NotifyStateChanged()
as follows:
private void NotifyStateChanged() => OnChange?.Invoke();
This method triggers the
OnChange
event. You should call this method from your logic after fulfilling whatever task it does.
In your todo Component, add the
StateHasChanged
method to the event delegate used in yourTodoItem
class thus:
@functions
{
protected override void OnInit()
{
state.OnChange += StateHasChanged;
}
}
Hope this helps. If it does, please don't fail to accept it as the answer
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
You should do the following:
Define an action delegate in your class:
public event Action OnChange;
In this very class define a method
NotifyStateChanged()
as follows:
private void NotifyStateChanged() => OnChange?.Invoke();
This method triggers the
OnChange
event. You should call this method from your logic after fulfilling whatever task it does.
In your todo Component, add the
StateHasChanged
method to the event delegate used in yourTodoItem
class thus:
@functions
{
protected override void OnInit()
{
state.OnChange += StateHasChanged;
}
}
Hope this helps. If it does, please don't fail to accept it as the answer
You should do the following:
Define an action delegate in your class:
public event Action OnChange;
In this very class define a method
NotifyStateChanged()
as follows:
private void NotifyStateChanged() => OnChange?.Invoke();
This method triggers the
OnChange
event. You should call this method from your logic after fulfilling whatever task it does.
In your todo Component, add the
StateHasChanged
method to the event delegate used in yourTodoItem
class thus:
@functions
{
protected override void OnInit()
{
state.OnChange += StateHasChanged;
}
}
Hope this helps. If it does, please don't fail to accept it as the answer
edited Nov 19 at 20:50
Kirk Woll
60.5k16157172
60.5k16157172
answered Nov 18 at 22:29
Issac
1,0391312
1,0391312
add a comment |
add a comment |
up vote
1
down vote
Easy answer is "just fire StateHasChanged();
after modify your var":
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
StateHasChanged();
});
Because your method is async, rewrite as:
Task.Run(async () => //<--here async
{
//Simulate async work
Task.Run( async () => {
await Task.Run( () => {} ); //<--- await
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
});
//Update property
Title = Title + " - Done";
StateHasChanged();
});
To avoid anti-pattern and write clean code, your ModelView may have a public event to let know UI it has changed, just connect this event on UI to StateHasChanged();
.
I write here the Blazor Counter sample modified to do this:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" onclick="@IncrementCount">
Click me @s <!-- here var -->
</button>
@functions {
int currentCount = 0;
string s = "";
void IncrementCount()
{
currentCount++;
Task.Run(() =>
{
//Simulate work
Task.Run( async () => {
await Task.Run( () => {} );
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));}
);
//Update property
s = s + " - Done";
StateHasChanged();
});
}
}
}
add a comment |
up vote
1
down vote
Easy answer is "just fire StateHasChanged();
after modify your var":
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
StateHasChanged();
});
Because your method is async, rewrite as:
Task.Run(async () => //<--here async
{
//Simulate async work
Task.Run( async () => {
await Task.Run( () => {} ); //<--- await
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
});
//Update property
Title = Title + " - Done";
StateHasChanged();
});
To avoid anti-pattern and write clean code, your ModelView may have a public event to let know UI it has changed, just connect this event on UI to StateHasChanged();
.
I write here the Blazor Counter sample modified to do this:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" onclick="@IncrementCount">
Click me @s <!-- here var -->
</button>
@functions {
int currentCount = 0;
string s = "";
void IncrementCount()
{
currentCount++;
Task.Run(() =>
{
//Simulate work
Task.Run( async () => {
await Task.Run( () => {} );
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));}
);
//Update property
s = s + " - Done";
StateHasChanged();
});
}
}
}
add a comment |
up vote
1
down vote
up vote
1
down vote
Easy answer is "just fire StateHasChanged();
after modify your var":
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
StateHasChanged();
});
Because your method is async, rewrite as:
Task.Run(async () => //<--here async
{
//Simulate async work
Task.Run( async () => {
await Task.Run( () => {} ); //<--- await
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
});
//Update property
Title = Title + " - Done";
StateHasChanged();
});
To avoid anti-pattern and write clean code, your ModelView may have a public event to let know UI it has changed, just connect this event on UI to StateHasChanged();
.
I write here the Blazor Counter sample modified to do this:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" onclick="@IncrementCount">
Click me @s <!-- here var -->
</button>
@functions {
int currentCount = 0;
string s = "";
void IncrementCount()
{
currentCount++;
Task.Run(() =>
{
//Simulate work
Task.Run( async () => {
await Task.Run( () => {} );
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));}
);
//Update property
s = s + " - Done";
StateHasChanged();
});
}
}
}
Easy answer is "just fire StateHasChanged();
after modify your var":
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
StateHasChanged();
});
Because your method is async, rewrite as:
Task.Run(async () => //<--here async
{
//Simulate async work
Task.Run( async () => {
await Task.Run( () => {} ); //<--- await
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
});
//Update property
Title = Title + " - Done";
StateHasChanged();
});
To avoid anti-pattern and write clean code, your ModelView may have a public event to let know UI it has changed, just connect this event on UI to StateHasChanged();
.
I write here the Blazor Counter sample modified to do this:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" onclick="@IncrementCount">
Click me @s <!-- here var -->
</button>
@functions {
int currentCount = 0;
string s = "";
void IncrementCount()
{
currentCount++;
Task.Run(() =>
{
//Simulate work
Task.Run( async () => {
await Task.Run( () => {} );
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));}
);
//Update property
s = s + " - Done";
StateHasChanged();
});
}
}
}
edited Nov 19 at 7:52
answered Nov 19 at 7:42
dani herrera
27.4k344107
27.4k344107
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53364149%2fupdate-a-property-asynchronous%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Why not add a callback event/handler in
TodoItem
(likeIsDoneComplete
) of typeAction
that your view registers in order to callStateHasChanged
?– Kirk Woll
Nov 18 at 19:23
Yes, I think my VM need update the view or notify the view.
– Orwel
Nov 19 at 20:47