0

I have a WPF application using mah metro where I have a tab control

  <Controls:MetroAnimatedTabControl Grid.Column="3" Grid.Row="1" SelectedIndex="{Binding SelectedTabIndex,Mode=TwoWay}">
        <TabItem Header="Manual Control">
            <view:ManualControlView DataContext="{Binding ManualControlViewModel}"/>
        </TabItem>
        <TabItem Header="Set up">
            <view:SetupView DataContext="{Binding SetupViewModel}"/>
        </TabItem>
    </Controls:MetroAnimatedTabControl>

I am setting the datacontext in the TabItem. I am creating a TcpCllient and passing that reference to each ViewModel. When I am doing this in the constructor everything works fine.

  public MainViewModel()
    {
        _client = new TcpClient(IP_ADDRESS, PORT);
        _client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
        _master = ModbusIpMaster.CreateIp(_client);

        ManualControlViewModel = new ManualControlViewModel(_master);
        SetupViewModel = new SetupViewModel(_master);

    }

However, I don't wish to create the TcpClient in the constructor. Instead I wish to create it when I hit a "Connect" button in my window. However, when I click my "Connect" button to execute a OnConnect method to do this my views are not getting set to the datacontext.

  private void OnConnect(object obj)
    {
        _client = new TcpClient(IP_ADDRESS, PORT);
        _client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
        _master = ModbusIpMaster.CreateIp(_client);
        Connected = _client.Connected;

        ManualControlViewModel = new ManualControlViewModel(_master);
        SetupViewModel = new SetupViewModel(_master);          

        StartReadingInfo();
    }

Is it possible to accomplish this?

mrsargent
  • 2,267
  • 3
  • 19
  • 36
  • See my answer here http://stackoverflow.com/questions/5650812/how-do-i-bind-a-tabcontrol-to-a-collection-of-viewmodels/5651542#5651542 which illustrates how to work with the TabControl using MVVM. Your button should be bound to an ICommand within your view model (whichever is appropriate), and *that* should update the other view models already bound to the UI. Your properties should also implement INotifyPropertyChanged in order to inform the UI that property values have ... changed. –  Dec 15 '16 at 15:44

1 Answers1

1

When you update properties of ViewModel, you should notify Control that properties changed.

        public class ViewModel : INotifyPropertyChanged
        {

            public SetupViewModel SetupViewModel 
            {
                get { return m_SetupViewModel; }
                set
                {
                    m_SetupViewModel = value;
                    OnPropertyChanged();
                }
            }

            public ManualControlViewModel ManualControlViewModel
            {
                get { return m_ManualControlViewModel; }
                set
                {
                    m_ManualControlViewModel = value;
                    OnPropertyChanged();
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;

            private void OnConnect(object obj)
            {
                _client = new TcpClient(IP_ADDRESS, PORT);
                _client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                _master = ModbusIpMaster.CreateIp(_client);
                Connected = _client.Connected;

                ManualControlViewModel = new ManualControlViewModel(_master);
                SetupViewModel = new SetupViewModel(_master);

                StartReadingInfo();
            }

            private void OnPropertyChanged([CallerMemberName] string PropertyName = "")
            {
                var handler = PropertyChanged;
                if (handler != null) handler(this, new PropertyChangedEventArgs(PropertyName));
            }

            private ManualControlViewModel m_ManualControlViewModel;
            private SetupViewModel m_SetupViewModel;
        }