3
votes

I am making a UWP and cannot correctly grasp DataBinding and INotifyPropertyChanged I am trying to bind some TextBox in a ContentDialog to properties in my code-behind cs file.

Here's my view model:

class UserViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public string _fname { get; set; }
    public string _lname { get; set; }    

    public string Fname
    {
        get { return _fname; }
        set
        {
            _fname = value;
            this.OnPropertyChanged();
        }
    }

    public string Lname
    {
        get { return _lname; }
        set
        {
            _lname = value;
            this.OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {            
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Code behind:

public sealed partial class MainPage : Page
{    
    UserViewModel User { get; set; }

    public MainPage()
    {
        this.InitializeComponent();     
        User = new UserViewModel();
    }
    ....
    ....
    private void SomeButton_Click(object sender, TappedRoutedEventArgs e)
    {
        //GetUserDetails is a static method that returns UserViewModel
        User = UserStore.GetUserDetails();

        //show the content dialog
        ContentDialogResult result = await UpdateUserDialog.ShowAsync();
    }
}

Here's the XAML for the ContentDialog:

<ContentDialog Name="UpdateUserDialog">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>                               
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*"></ColumnDefinition>
        <ColumnDefinition Width="1*"></ColumnDefinition>
    </Grid.ColumnDefinitions>

    <TextBox Grid.Row="0"
        Grid.Column="0"
        Grid.ColumnSpan="2"
        Name="tbFirstNameUpdate"
        Text="{x:Bind Path=User.Fname, Mode=OneWay}"                           
        Style="{StaticResource SignUpTextBox}"/>

    <TextBox Grid.Row="1"
        Grid.Column="0"
        Grid.ColumnSpan="2"
        Name="tbLastNameUpdate"
        Text="{x:Bind Path=User.Lname, Mode=OneWay}"
        Style="{StaticResource SignUpTextBox}"/>
</ContentDialog>

NOTE: Binding works well when I initialize the view model in the MainPage constructor itself like this:

User = new UserViewModel { Fname = "name", Lname = "name" };
2

2 Answers

1
votes

You don't fire a PropertyChanged event when you replace the value of the User property with a new view model instance.

You may however simply replace

User = UserStore.GetUserDetails();

by

var user = UserStore.GetUserDetails();
User.Fname = user.Fname;
User.Lname = user.Lname;

and hence update the existing instance of your view model.

0
votes

You should set the DataContext property to the view model instance:

public MainPage()
{
    this.InitializeComponent();     
    User = new UserViewModel();
    DataContext = User;
}

See: https://docs.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth