Nariman Ma
Nariman Ma

Reputation: 53

BindableBase - SetProperty does not work using the instance of the ViewModel

I am trying to set the property of the MainViewModel from LoginViewModel using an instance of the MainViewModel inside LoginViewModel . But the binding in XAML does not get notified ! I set the break point inside the MainViewModel and it shows the value is being set, but if its set through instance it does not work. Can anyone help? Below are the codes for both viewmodel. As you can see, in my loginviewmodel I set the public property using the instance of MainViewModel :

MainViewModel.Instance.Mainviewpageindex = 1;

MainViewModel

namespace DataRetrieval.ViewModels
{
    public class MainViewModel : BindableBase
    {
        private static MainViewModel _instance = new MainViewModel();
        public static MainViewModel Instance { get { return _instance; }


        }

        private int _mainviewpageindex;
        public int Mainviewpageindex
        {
            get { 
                return _mainviewpageindex; }
            set { 
               SetProperty(ref _mainviewpageindex, value);
              //  _mainviewpageindex = value;
               // RaisePropertyChangedEvent("Mainviewpageindex");
            } 
        }

        public MainViewModel()
        {
            Mainviewpageindex = 0;

        }

          public DelegateCommand<object> _loginCommand;
          public ICommand LoginCommand
          {
              get
              {
                  _loginCommand = new DelegateCommand<object>(Login, VerifyLogin);
                  return _loginCommand;
              }
          }
            private void Login(object context)
            {
                Mainviewpageindex = 1;
            }


            private bool VerifyLogin(object context)
            {
                return true;
            }

    }

LoginViewModel

namespace DataRetrieval.ViewModels
{

        public class LoginViewModel : BindableBase
        {
          //  public SecureString SecurePassword { private get; set; }
            private string _uname;
            public string Uname
            {
                get { return _uname; }
                set { 
                    SetProperty(ref _uname, value);
                   _loginCommand.RaiseCanExecuteChanged();

                }
            }
            private SecureString _securePassword;
            public SecureString SecurePassword
            {
                get { return _securePassword; }
                set {
                    SetProperty(ref _securePassword, value);
                    _loginCommand.RaiseCanExecuteChanged();
                }
            }

            public LoginViewModel()
            {

            }

            public DelegateCommand<object> _loginCommand;
            public ICommand LoginCommand
            {
                get
                {
                    _loginCommand = new DelegateCommand<object>(Login, VerifyLogin);
                    return _loginCommand;
                }
            }

            private void Login(object context)
            {
                if (SecurePassword != null || Uname != null)
                {
                    //PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
                   // bool validated = ctx.ValidateCredentials(Uname, SecureStringToString(SecurePassword));
                  MainViewModel.Instance.Mainviewpageindex = 1;

                }else
                {

                }

            }
            String SecureStringToString(SecureString value)
            {
                IntPtr valuePtr = IntPtr.Zero;
                try
                {
                    valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
                    return Marshal.PtrToStringUni(valuePtr);
                }
                finally
                {
                    Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
                }
            }

            private bool VerifyLogin(object context)
            {
                return true;
            }
        }

    }

XAML:

<Window x:Class="DataRetrieval.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:views="clr-namespace:DataRetrieval.Views"
           xmlns:prism="http://www.codeplex.com/prism"
          xmlns:viewModels="clr-namespace:DataRetrieval.ViewModels"
        Title="Data Retrieval Tool" Height="Auto" Width="900" Icon="Resources/colorful_query_mark_light_bulb_28261523_y2o_icon.ico">
    <Window.DataContext>
        <viewModels:MainViewModel />
    </Window.DataContext>
    <TabControl Name="TabControl1" BorderBrush="{x:Null}" Background="White" SelectedIndex="{Binding Mainviewpageindex, UpdateSourceTrigger=PropertyChanged,  Mode=TwoWay}">
        <TabControl.ItemContainerStyle>
            <Style TargetType="{x:Type TabItem}">
                <Setter Property="Visibility" Value="Collapsed"/>
            </Style>
        </TabControl.ItemContainerStyle>
        <TabItem Header="General">

            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*" MaxWidth="300"/>
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="50"/>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="300"/>
                </Grid.RowDefinitions>
                <views:Login HorizontalAlignment="Center" VerticalAlignment="Center"  Grid.Column="1" Grid.Row="1" />
                <TextBlock  TextWrapping="Wrap" TextAlignment="Center" Text="User your OneAbbott domain user name and password to login into the system" Grid.Column="1" Grid.Row="2"/>
                <Button  x:Name="btnLogin" Content="Login" Margin="20" Command="{Binding LoginCommand}"/>
            </Grid>



        </TabItem>
        <TabItem Header="Second Tab">
            <StackPanel>
                <TextBlock  TextWrapping="Wrap" TextAlignment="Center" Text="Login Successfull" Grid.Column="1" Grid.Row="2"/>


            </StackPanel>
        </TabItem>

    </TabControl>
</Window>

Upvotes: 0

Views: 2667

Answers (2)

Nariman Ma
Nariman Ma

Reputation: 53

It seems the best way to implement the communication between ModelViews is using prism Event Aggregation !

An example of it is provided here on MSDN: https://msdn.microsoft.com/en-us/library/ff921173(v=pandp.40).aspx

Upvotes: 0

Brian Noyes
Brian Noyes

Reputation: 2070

You are dealing with two different instances of your MainViewModel. The one actually hooked up to your view is constructed by the XAML parser when it hits the code that is setting your data context.

The other you are creating as a separate static object inside your viewmodel and exposing through the Instance property.

You need a different way to communicate between the ViewModel instances. Pub-Sub events in Prism are the best way to deal with this kind of scenario, although using a CompositeCommand would also work.

Upvotes: 1

Related Questions