2

I've never used IOC in any of my apps, and today I decided to learn how to use it but I'm having some issues with bindings.

What happens is that bound values are updated as soon as the page shows, but changing some of them later doesn't reflect to the page.

Here are some snippets of the part that's causing issues:

service

public class TimerService : BindableBase, ITimerService
{
    public TimerService()
    {   
        RemainingTime = UpdateInterval;
        var updateTimer = new DispatcherTimer
        {
            Interval = TimeSpan.FromSeconds(1)
        };            
        updateTimer.Tick += UpdateTimerOnTick;
        updateTimer.Start();
    }        

    private double _remainingTime;

    public int UpdateInterval { get; set; } = 90;

    public double RemainingTime
    {
        get { return _remainingTime; }
        set { 
            // From Template10, it calls RaisePropertyChanged (and even calling it manually doesn't help)
            Set(ref _remainingTime, value); 
        }
    }

    private void UpdateTimerOnTick(object sender, object o)
    {
        RemainingTime -= 1;
        if (Math.Abs(RemainingTime) < 0.05) RemainingTime = UpdateInterval;
        // Timer is running fine as I can see the prints
        Debug.WriteLine($"{RemainingTime}");            
    }
}

locator

public class ViewModelLocator
{
    static ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            SimpleIoc.Default.Register<ITimerService, DesignTimeTimerService>();
        }
        else
        {
            SimpleIoc.Default.Register<ITimerService, TimerService>(true);
        }

        SimpleIoc.Default.Register<MainPageViewModel>();
    }

    public MainPageViewModel MainPageViewModel => ServiceLocator.Current.GetInstance<MainPageViewModel>();
}

viewModel

public class MainPageViewModel : ViewModelBase
{

    public ITimerService TimerService { get; }

    public MainPageViewModel(ITimerService timerService)
    {
        TimerService = timerService;
    }

}

page

<Page x:Class="Views.MainPage"
      ...
      DataContext="{Binding Source={StaticResource ViewModelLocator}, Path=MainPageViewModel}"
      mc:Ignorable="d">

      ...

      <ProgressBar Maximum="{x:Bind ViewModel.TimerService.UpdateInterval}"
                   ...
                   Value="{x:Bind ViewModel.TimerService.RemainingTime, Mode=OneWay, Converter={StaticResource EmptyConverter}}" />


      ...

      (.cs file)

      private MainPageViewModel ViewModel => DataContext as MainPageViewModel;

What I'd expect is to have ProgressBar's value decreasing as the timer goes, but it just stays still on the very first value that I set.

I've also tried adding an empty converter to see if something happens but it's like ProgressBar never receives the update event.

Do you have any hints on this?

StepTNT
  • 3,867
  • 7
  • 41
  • 82
  • Your setup looks fine to me. I've had some issues in the past with the `ProgressBar` tough, changes in the `Value` property would only show up if the binding `Mode` was set to `TwoWays`. I cannot reproduce this behaviour right now, but its worth a shot. You may also want to bind to a `Textblock.Text` or something similar to verify its not a problem with the `ProgressBar`. – Florian Moser Sep 15 '16 at 07:36
  • I've just finished doing some tests: `TwoWay` doesn't help, but guess what? Replacing `x:Bind` with `Binding` solved it. I guess where we shoud use `x:Bind` since it always fails. EDIT: not posting this as answer yet because I'd like to know if someone is able to make this work with `x:Bind`. – StepTNT Sep 15 '16 at 08:16
  • Could you please provide the reproduce project? Upload to github or somewhere. – Sunteen Wu Sep 19 '16 at 10:09
  • @Sunteen-MSFT stripped down repro [here](https://www.dropbox.com/s/wm8hgso25wr7asv/TimerIocRepro.zip?dl=0) – StepTNT Sep 21 '16 at 10:34

0 Answers0