-1

I'm creating an application for UWP using MVVM principles.

I have a Page which contains the standard toolbar, with the actual content inside the ScrollView below it being dynamic depending on where the user navigated from;

<ScrollViewer>
        <StackPanel Orientation="Vertical">
            <ContentControl HorizontalAlignment="Stretch" 
                            VerticalAlignment="Stretch" 
                            Content="{x:Bind viewModel.Content}">
            </ContentControl>
        </StackPanel>
</ScrollViewer>

A simplified version of the content I bind to that section looks something like this:

public class Content : StackPanel
{
    ContentViewModel ViewModel;
    TextBlock txtInformation;

    public Content()
    {
        Orientation = Orientation.Vertical;
        ViewModel = new ContentViewModel();                        
        txtInformation = new TextBlock();

        txtInformation.SetBinding(TextBlock.TextProperty,
                                  new Binding()
                                  {
                                      Mode = BindingMode.OneWay,
                                      Source = ViewModel.Item,
                                      Path = new 
                                      PropertyPath("Information"),
                                      TargetNullValue = "No information found"
                                  });

        Children.Add(txtInformation);
    }
}

And lastly, here is what the simplified version of the view model for the content looks like:

public class ContentViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    MyObject _item;

    public ContentViewModel()
    {
        Item = new MyObject()
        {
            Information = "Information goes here"
        };  
    }

    public MyObject Item
    {
        get
        {
            return _item;
        }
        set
        {
            _item = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item"));
        }
    }
}

Initially the binding seems to work, as when the page loads the TextBlock has "No information found" as its text value. But when the property changes there's no update to the UI.

This only seems to be a problem when setting a control's binding in C# with the SetBinding() method instead of in XAML with the {x:Bind} extension as my other pages which use XAML for their binding update correctly.

No errors are thrown.

Marc Cilliers
  • 95
  • 1
  • 14
  • _"No errors are thrown"_ -- not even messages to the debug output? Anyway, you are using `TextBox.TextProperty`, even though the target object of the binding is a `TextBlock`. So, first thing I'd try would be to use `TextBlock.TextProperty` instead. – Peter Duniho Jan 12 '18 at 09:49
  • My mistake, that was a typo. Well spotted! I haven't checked the output much but will have a look – Marc Cilliers Jan 12 '18 at 09:52
  • The output doesn't seem to show any useful information regarding the issue. Thank you for the suggestion. – Marc Cilliers Jan 12 '18 at 11:47
  • 2
    It would really help if you create a fresh UWP project and write your example into it... then copy the example codes into your question (mostly complete). Things like `public class ContentViewModel()` mean that I can't trust your posted code to be anyhow problem related. – grek40 Jan 12 '18 at 12:27
  • Following on from @grek40, it could be useful to put this sample project into Github and send the link as well. So other's can reproduce your issue on their own machines – jsmyth886 Jan 12 '18 at 16:53
  • No. Don't use GitHub as a place to support your question, as @jsmyth886 suggests. Your question needs to be self-contained, with a good [mcve] that reliably reproduces the problem. Feel free to include a GitHub link as _optional_ additional information, but the question needs to stand on its own, without use of external resources. – Peter Duniho Jan 13 '18 at 05:15
  • I only mentioned a sample project on Github as this is not a Minimal, Complete or Verifiable example. I did not say to use Github as the only source of code for the question, I said it could be useful. – jsmyth886 Jan 13 '18 at 07:56
  • May be spelling mistakes, `Content="{x:Bind ViewModel.Content}"` the first letter of "ViewModel" should be lowercase. – tao Jan 15 '18 at 03:00
  • Apologies for the late reply, I have fixed the spelling and syntax error. I will create a simple UWP for reproducing the error and provide a link to it on GitHub the first moment I get during the day. – Marc Cilliers Jan 15 '18 at 06:01
  • So in the progress of creating the sample project, I discovered that by simplifying the question to the extent which I did, I eliminated the problem altogether. How embarrassing. I've updated the question to reflect the code I have, in that I am attempting to bind to the property of an object instead of a string. I hope this more clearly reveals the error. – Marc Cilliers Jan 16 '18 at 11:47

3 Answers3

0
Content="{x:Bind ViewModel.Content, Mode=Oneway}">

The standard mode with x:Bind is OneTime... which works only at the beginning...

thezapper
  • 486
  • 4
  • 13
0

Instead of

txtInformation.SetBinding(TextBlock.TextProperty,
                              new Binding()
                              {
                                  Mode = BindingMode.OneWay,
                                  Source = ViewModel.Item,
                                  Path = new 
                                  PropertyPath("Information"),
                                  TargetNullValue = "No information found"
                              });

The Source & PropertyPath properties should be set as follows:

txtInformation.SetBinding(TextBlock.TextProperty,
                              new Binding()
                              {
                                  Mode = BindingMode.OneWay,
                                  Source = ViewModel,
                                  Path = new 
                                  PropertyPath("Item.Information"),
                                  TargetNullValue = "No information found"
                              });

Thanks to @grek40 for suggesting I recreate the issue in a sample app. It clarified the source of the error.

Marc Cilliers
  • 95
  • 1
  • 14
-3

Try like this. I think there is something wrong with the implementation of INotifyPropertyChanged interface.

public class Employee : INotifyPropertyChanged 
{
    private string _name;
    private string _organization;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            RaisePropertyChanged("Name");
        }
    }

    public string Organization
    {
        get { return _organization; }
        set
        {
            _organization = value;
            RaisePropertyChanged("Organization");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
}
Shakir Ahmed
  • 559
  • 4
  • 13
  • Thank you for the suggestion. I doubt it's the implementation of the INotifyPropertyChanged interface since I use the same implementation in the View Models which are bound to the XAML views that successfully update. I gave it a try anyway but, unfortunately, to no avail. – Marc Cilliers Jan 12 '18 at 11:44
  • 2
    Your `RaisePropertyChanged` implementation is worse than `PropertyChanged?.Invoke` and it won't solve the problem. See also: https://stackoverflow.com/a/22268601/5265292 – grek40 Jan 12 '18 at 12:32