curiousity
curiousity

Reputation: 4741

Dynamic binding?

May be not a right title for the question but I will try to explain: My TextBox already bound to a property like:

class MyViewModel : INotifyPropertyChanged
    public string TextVal
    {
        get
        {
             if (View != null)
                  { 
                         return View.Model.TextForValueField;   // other satrts
                   }
                 return defaultModel.TextForValueField;// first start

        set
        {
             .....//some setters logic with View.Model.TextForValueField
        } 
    }

When program starts the View is not open so getter binds the value of the field to the value in default model and it is correct, but then , when I open new View my getter correctly returns values from corresponding View.Model.TextForValueField but the field of TextBox on my windows ribbon menu shows the initial value from default model (?) Why?? the xaml for binding is :

<Setter Property="Text" Value="{Binding MyViewModel.TextVal, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

Perhaps there is a way to call getter once more when a View starts? Something like "Refresh" for ribbons??

My property changed function

protected void RaisePropertyChanged(string propName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propName));
            }
        }

Upvotes: 2

Views: 124

Answers (1)

Sinatr
Sinatr

Reputation: 21999

When you forward Model property via ViewModel property you have to carry on its updates manually.

public class Model
{
    public string Property {get; set;}
}

public class ViewModel
{
    public string BindProperty
    {
        get { return modelInstance.Property; }
        set
        {
            modelInstance.Property = value;
            OnPropertyChanged();
        }
    }
}

When you bind to BindProperty your view is not notified when Model.Property gets changed.

One possible solution is to make Model implement INotifyPropertyChanged too and forward that notification. Another (not advised) is bind to Model.Property directly (model still has to implement INotifyPropertyChanged).

public class Model: NotifyPropertyChangedBase
{
    private string _property;
    public string Property
    {
        get { return _property; }
        set
        {
            _property = value;
            OnPropertyChanged();
        }
    }
}

public class ViewModel: NotifyPropertyChangedBase
{
    public string BindProperty
    {
        get { return modelInstance.Property; }
        set
        {
            modelInstance.Property = value;
            OnPropertyChanged();
        }
    }

    public ViewModel()
    {
        modelInstance.PropertyChanged += Model_PropertyChanged;
    }

    void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // forward change notification to View
        if(e.PropertyName == "Property")
            OnPropertyChanged("BindProperty");
    }
}

public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string property = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }
}

Upvotes: 1

Related Questions