简体   繁体   中英

UWP C# MVVM How To Access ViewModel from Other Page

I am tying to further understand MVVM with some example scenario. I have a rootpage with a 'maindisplay' textblock . I would like to display 'status' or 'scenarios' from activation of any form of UI eg. togglebutton on the 'maindisplay' textblock .

I am able to bind the the page navigation info in the rootpageviewmodel to the textblock . However, I am not able to achieve the result when displaying info from different page. I have checked another post multiple-viewmodels-in-same-view & Accessing a property in one ViewModel from another it's quite similar but it didn't work.

Please help. Thanks.

While accessing the RootPageViewModel should retain the instance?

View

<TextBlock Text="{x:Bind RootViewModel.MainStatusContent, Mode=OneWay}"/>

RootPage.xaml.cs

        public sealed partial class RootPage : Page
        {
            private static RootPage instance;
            public RootPageViewModel RootViewModel { get; set; }
    
            public RootPage()
            {
                RootViewModel = new RootPageViewModel();
    
                this.InitializeComponent();
    
                // Always use the cached page
                this.NavigationCacheMode = NavigationCacheMode.Required;
            }
    
            public static RootPage Instance
            {
                get
                {
                    if (instance == null)
                    {
                        instance = new RootPage();
                    }
                    return instance;
                }
            }
         private void nvTopLevelNav_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
            {
                if (args.IsSettingsInvoked)
                {
                    contentFrame.Navigate(typeof(SettingsPage));
    
                    RootViewModel.MainStatusContent = "Settings_Page";
                }
                else
                { 
                    var navItemTag = args.InvokedItemContainer.Tag.ToString();        
                    
                    RootViewModel.MainStatusContent = navItemTag;
                                     
                    switch (navItemTag)
                    {
                        case "Home_Page":   
                            contentFrame.Navigate(typeof(HomePage));
                            break;
    
                        case "Message_Page":  
                            contentFrame.Navigate(typeof(MessagePage));
                            break;
                    }
                    
                }
             }
        }
        

RootPage ViewModel :

public class RootPageViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private static RootPageViewModel instance = new RootPageViewModel();
    public static RootPageViewModel Instance
    {
        get
        {
            if (instance == null)
                instance = new RootPageViewModel();

            return instance;
        }
    }

    public RootPageViewModel()
    {
    }

    private string _mainStatusContent;
    public string MainStatusContent
    {
        get
        {
            return _mainStatusContent;
        }
        set
        {
            _mainStatusContent = value;
            OnPropertyChanged();
        }
    }

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

MessagePage.xaml.cs - to access RootPage ViewModel

public sealed partial class MessagePage : Page
{
    public MessagePageViewModel MessageViewModel { get; set; }

    public MessagePage()
    {
        MessageViewModel = new MessagePageViewModel();

        this.InitializeComponent();

        // Always use the cached page
        this.NavigationCacheMode = NavigationCacheMode.Required;
    }

    private void Message1_Checked(object sender, RoutedEventArgs e)
    {
        RootPageViewModel.Instance.MainStatusContent = "Message 1 Selected";
    }

    private void Message1_Unchecked(object sender, RoutedEventArgs e)
    {
        RootPageViewModel.Instance.MainStatusContent = "Message 1 De-Selected";
    }
}

When I debug the value did write to the instance but did't update the TextBlock . Did I do anything wrong in my XAML binding? 在此处输入图像描述 在此处输入图像描述

UWP C# MVVM How To Access ViewModel from Other Page

The better way is make static variable for RootPage, but not make singleton instance for RootPage and RootPageViewModel .

For example:

public RootPage ()
{
    this.InitializeComponent();
    this.NavigationCacheMode = NavigationCacheMode.Required;
    Instance = this;
    RootViewModel = new RootPageViewModel();
}

public static RootPage Instance;

Usage

private void Message1_Checked(object sender, RoutedEventArgs e)
{

    RootPage.Instance.RootViewModel.MainStatusContent = "Message 1 Selected";
}

private void Message1_Unchecked(object sender, RoutedEventArgs e)
{
    RootPage.Instance.RootViewModel.MainStatusContent = "Message 1 De-Selected";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM