不在构造函数中设置视图模型的数据上下文

Setting Datacontext of viewmodel not in constructor

我有一个 WPF 应用程序使用 mah metro 我有一个 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>

我正在 TabItem 中设置 datacontext。我正在创建一个 TcpCllient 并将该引用传递给每个 ViewModel。当我在构造函数中执行此操作时,一切正常。

  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);

    }

但是,我不想在构造函数中创建 TcpClient。相反,我希望在我的 window 中点击 "Connect" 按钮时创建它。但是,当我单击 "Connect" 按钮执行 OnConnect 方法来执行此操作时,我的视图未设置为 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();
    }

有可能实现吗?

当您更新 ViewModel 的属性时,您应该通知 Control 属性已更改。

        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;
        }