0
votes

Problem:

My Viewmodel creates a instance of a controller mycontroller and the property Busy shall be passed to the View and updated in the View based on the controller state, but my View doesn't get updated. The other property Busy2 is updated based on the current state. Bindablebase implements the I

Question:

Why the property Busy in the ViewModel is not updated? The mycontroller.Busy property is updating, but not the view.

Framework & Tools:

PRISM 6.3.0

Fody.Propertychanged

View:

<TextBlock Text="{Binding Path=Busy}"></TextBlock>
<TextBlock Text="{Binding Path=Busy2}"></TextBlock>

ViewModel:

public class Controller
    {
        public bool Busy { get; private set; }

        public async void GetValue()
        {
            Busy = true;
            await Task.Delay(5000);
            Busy = false;
        }
    }

    public class MyViewModel : BindableBase
    {
        private readonly Controller _mycontroller;
        public DelegateCommand<string> RunCommand { get; private set; }

        // This property is not updated in the view
        public bool Busy
        {
            get { return _mycontroller.Busy; }
        }

        // Works as aspected
        public bool Busy2 { get; set; }

        public MyViewModel()
        {
            _mycontroller = new Controller();
            RunCommand = new DelegateCommand<string>(Run, Canrun).ObservesProperty((() => _mycontroller.Busy));
        }

        private bool Canrun(string arg)
        {
            return _mycontroller.Busy != true;
        }

        private void Run(string obj)
        {

            Busy2 = true;
            _mycontroller.GetValue();


        }
    }

Update:

I added the Bindablebase from Prism, because is implement the INotifyPropertyChanged, but the view is still not updated. I refactored the code and I set a breakpoint to set { SetProperty(ref _busy, value); } and the breakpoint is never reached.

I removed the Propertychanged.Fody nuget package too.

ViewModel:

   public class Controller : BindableBase
    {
        private bool _busy;
        public bool Busy
        {
            get { return _busy; }
            set { SetProperty(ref _busy, value); }
        }

        public Controller()
        {

        }

        public void DoWork1()
        {
            for (var i = 0; i < 10; i++)
            {
                Thread.Sleep(1000);
                _busy = !_busy;
                Debug.WriteLine(_busy.ToString());
            }
        }

        public void DoWork2()
        {
            _busy = !_busy;

        }
    }

    public class MainWindowViewModel : BindableBase
    {
        private Controller mycontroller;
        private string _title = "Prism Unity Application";

        public DelegateCommand RunCommand { get; private set; }

        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public bool Busy
        {
            get { return mycontroller.Busy; }
        }

        public MainWindowViewModel()
        {
            RunCommand = new DelegateCommand(Execute);
            mycontroller = new Controller();

        }

        private void Execute()
        {
            mycontroller.DoWork1();
        }
    }

View:

<Window x:Class="PropertytestPrism.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">
    <StackPanel>
        <Button Command="{Binding RunCommand}" Content="Run"></Button>
        <TextBlock Text="{Binding Busy}"></TextBlock>

    </StackPanel>
</Window>

Update 2

  1. Failure: Missing INotifypropertychanged for the class Controller

The View is still not updated and the reason for this is my Delegatecommandmethod, which executes mycontroller.DoWork1();

Question:

Why the View is not updated? If I execute the method inside the DelegateCommandmethod?

2

2 Answers

1
votes

You should implement INotifyPropertyChanged by your Controller class. Property is changed inside Controller class and this changing should be notified:

public class Controller : INotifyPropertyChanged
{
    private bool _busy;

    public bool Busy 
    {
        get
        {
            return  _busy;
        } 
        private set
        {
            SetField(ref _busy, value, "Busy"); }
        } 
    }

    public async void GetValue()
    {
        Busy = true;
        await Task.Delay(5000);
        Busy = false;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
           handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value))
        {
            return false;
        }

        field = value;
        OnPropertyChanged(propertyName);

        return true;
    }
}
0
votes

Try making your bindings work like this.

<TextBlock Text="{Binding Busy,Mode=OneWay}"></TextBlock>.

By default bindings are one time and so they wont be updated even on the property changed notification.