1
votes

I have a WinRT project based on prism with several pages, usercontrols etc. For some reason I need to bind several views to a single model object accessed by the the viewmodels (each one belonging to a view). The single model object is injected by a Unity container like other objects, that need to be singleton-like as the eventaggregator for instance. To keep things simple I made an example with only one bool variable bound to a checkbox in each view, that should be synchronized over the views. My problem is: When I check the box in the mainpage, the checkbox in a second page is following the value when navigating to that page(UserInpuPage in the example) BUT NOT the checkbox in the UserControl place on the Mainpage. After a debug session I saw the variables in the single model having the right values, but the GUI on the Usercontrol (MyUserControl in the example) is not updated. A Mechanism like GetBindingExpression(...) and then UpdateTarget() like in WPF seems not to exist in the WinRT library. For design reasons (using prism mvvm I don't want to break the concept of the autowire and dynamical instantiation of the vm's) a static context defined in the resources section of the page and/or usercontrol is not what I'm looking for.

How can I achieve the update of the checkbox in the usercontrol with the model the same way as it works for the userinputpage after navigating? Any help would be appreciated.

// Interface mendatory to work with Unitiy-Injection for RegisterInstance<ISingletonVM>(...)
public interface ISingletonVM
{
    bool TestChecked{ get; set; }
}

public class SingletonVM : BindableBase, ISingletonVM
{

    bool _testChecked = false;
    public bool TestChecked
    {
        get
        {
            return _testChecked;
        }

        set
        {
            SetProperty(ref _testChecked, value);
        }
    }
}

This is the relevant code in the viewmodels (same for every vm, but vm from usercontrol in this case):

class MyUserControlViewModel : ViewModel
{
    private readonly ISingletonVM _singletonVM;

    public MyUserControlViewModel(ISingletonVM singletonVM)
    {
        _singletonVM = singletonVM;
    }

    public bool TestChecked
    {
        get
        {
            return _singletonVM.TestChecked;
        }

        set
        {
            _singletonVM.TestChecked = value;
        }
    }
}

Relevant XAML code fragments for the three views:

MainPage:

<prism:VisualStateAwarePage x:Name="pageRoot"  x:Class="HelloWorldWithContainer.Views.MainPage"...>
...    
    <StackPanel Grid.Row="2" Orientation="Horizontal">
    <ctrl:MyUserControl ></ctrl:MyUserControl>
    <CheckBox IsChecked="{Binding TestChecked, Mode=TwoWay}" Content="CheckBox" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    </StackPanel>
 ...

UserInputPage:

<prism:VisualStateAwarePage x:Name="pageRoot"
                        x:Class="HelloWorldWithContainer.Views.UserInputPage" 
...
<CheckBox IsChecked="{Binding TestChecked, Mode=TwoWay}" Content="CheckBox" HorizontalAlignment="Left" Margin="440,190,0,0" VerticalAlignment="Top"/>
...

UserControl:

<UserControl
x:Class="HelloWorldWithContainer.Views.MyUserControl" prism:ViewModelLocator.AutoWireViewModel="True"    
<Grid>
    <CheckBox Content="CheckBox" IsChecked="{Binding TestChecked, Mode=TwoWay}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="282"/>
</Grid>

1

1 Answers

1
votes

Your user control never gets notified about changes in MyUserControlViewModel.TestChecked property and that's why the view is never updated. One thing you can do to fix this is to subscribe to your SingletonVM.PropertyChanged event in the constructor of MyUserControlViewModel. Your ISingletonVM needs to implement the INotifyPropertyChanged interface. So the constructor of MyUserControlViewModel will be something like this:

public MyUserControlViewModel(ISingletonVM singletonVM)
{
     _singletonVM = singletonVM;
     _singletonVM.PropertyChanged += (sender, args) => OnPropertyChanged("TestChecked");
}