1

I have a scenario where updating the View from the ViewModel using the INotifyPropertyChanged interface is not suitable.

Instead I'd like to refresh some of the bindings explicitly.

In WPF this seems to be possible by obtaining a BindingExpression from the control and call BindingExpression.UpdateTarget() (see How to force a WPF binding to refresh?).

Is something similar possible in MAUI? BindingExpression does not even seem to exist...

Background

I'm displaying a list of items, each of them has a CreatedAt timestamp. In the UI I want to display this as "7 minutes ago", for example. Therefore I created a value converter that converts a DateTime to a string. And of course the displayed string should update over time.

IMHO, updating the text in the UI should be a matter of the View in this case. I don't want to have an interval timer in my ViewModels. I prefer to have an interval timer in my View (in the code behind) that refreshes the binding of only those items currently visible.

Robert Hegner
  • 9,014
  • 7
  • 62
  • 98
  • Can you try to explain why it is not suitable, so I can convince you it is? – H.A.H. May 16 '23 at 08:20
  • @FreakyAli Your answer is the one in the link in the question: OnPropertyChanged(nameof(YourCollectionProperty)); As I tried to explain it to you, first - the OP obviously knows about your "answer", second - he is specifically asking for something different. – H.A.H. May 16 '23 at 09:53
  • 1
    You can run a timer from the code-behind and bind to a property in the code-behind as well. Then you bind from the XAML to the code-behind. No need to do it in the ViewModel. – Julian May 16 '23 at 11:12
  • @ewerspej this sounds promising, I will try that. – Robert Hegner May 16 '23 at 12:04

2 Answers2

0

"IMHO, updating the text in the UI should be a matter of the View in this case. I don't want to have an interval timer in my ViewModels. I prefer to have an interval timer in my View (in the code behind) that refreshes the binding of only those items currently visible."

I want to point out something important about MVVM.

When following MVVM architecture ViewModels should not know anything about the Views. However, your Views have access to the ViewModels all the time.

You are free to call a method from your ViewModel, at any time. Be it as response to event, received message, or something else.

Your View should already hold reference to your ViewModel, so by making a timer, and calling a method to update your data, you will not be violating any MVVM principles.

(If I did not convince you already, tell me to continue...)

H.A.H.
  • 2,104
  • 1
  • 8
  • 21
0

Unfortunately, Maui lacks any way to access the binding expression.

One solution is to create View properties that do what you want, and trigger property changes on a timer:

<Label Text="{Binding RelativeTime1, Source={RelativeSource Self}}" />

In view's code-behind:

MyViewModel VM => BindingContext as MyViewModel;

public RelativeTime1 => AsRelativeTime(VM.Time1);

// Each timer tick
public void Elapsed()
{
   OnPropertyChanged(nameof(RelativeTime1));
}
ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196