Data Retain After Changing DataContext/ Views in WPF

608 views Asked by At

I am new to WPF and want to build an application which will do serial communication with the my driver and from program i can set values to the driver.

I have managed to make a UI as shown in this figure here . If i press Blue View as pointed by the arrow at last, the view of my window is like this. If i press the Red View Option then the display is like this Setting button is where the arrow pointing at top right corner(below the close button of window) and when pressed my window will look like this.

Basically i am changing the BIG RECTANGLE content according to the button i have pressed for example (rectangle is blue when Blue view is clicked, rectangle filled up with Red and one label and a button to change the label when Red View is clicked)

So now my problem is I cannot retain the value i had set in this BIG RECTANGLE after i change the content of this BIG RECTANGLE. For example when i pressed the setting button and change the setting like this I am ready for communication in COM5 and the option to close the port can be pressed. Now before closing the port if I change the view of the BIG RECTANGLE by pressing Red View or Blue View then after press the setting button then i don't have that option to close port anymore and since I had already opened the com5 port earlier so when i try to open the port it will also give me error.

Please Help me with this. My visual studio solution explorer looks like this and My code in the button clicked event are as follows:

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void SerialPortOnOFFButton_Clicked(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("ON OFF Clicked");
        }

        private void SerialPortSettingButton_Clicked(object sender, RoutedEventArgs e)
        {
            DataContext = new SerialPortSettingView();
           
        }

        private void RedViewButton_Clicked(object sender, RoutedEventArgs e)
        {
            DataContext = new Redview();
        }

        private void BlueViewButton_Clicked(object sender, RoutedEventArgs e)
        {
            DataContext = new Blueview();
        }
    }

And my Solution explorer looks like this

2

There are 2 answers

3
Coops On BEST ANSWER

Each time you change the view you are creating a new object to set the DataContext to, if you kept the individual objects as private fields you could then simply set the DataContext to these:

    private SerialPortSettingView _serialPortSettingView;
    private RedView _redView;
    private BlueView _blueView;

    public MainWindow()
    {
        _serialPortSettingView = new SerialPortSettingView();
        _redView = new RedView();
        _blueView = new BlueView();
        InitializeComponent();
    }

    private void SerialPortOnOFFButton_Clicked(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("ON OFF Clicked");
    }

    private void SerialPortSettingButton_Clicked(object sender, RoutedEventArgs e)
    {
        DataContext = _serialPortSettingView;
    }

    private void RedViewButton_Clicked(object sender, RoutedEventArgs e)
    {
        DataContext = _redview;
    }

    private void BlueViewButton_Clicked(object sender, RoutedEventArgs e)
    {
        DataContext = _blueview;
    }

This way when you switch between views you'll be using the stored version and when you change values they will be stored in that View.

If I were doing this solution I would change the ContentControl to a TabControl (hide the headers) then create each View, with an accompanying ViewModel, as tabs. Then as each click event is fired you simply set the .SelectedIndex property of the TabControl. I'd create a MainWindowViewModel and set the MainWindow's DataContext to this in the constructor:

    private MainWindowViewModel = new MainWindowViewModel();

    public MainWindow()
    {
        DataContext = _mainWindowViewModel;
    }

And put all the logic in the MainWindowViewModel (you need to use commands). Using code behind isn't what WPF was meant for, you can read up on it all here with a good tutorial to follow - MVVM Tutorial

I don't want to over complicate things and stuff you with too much information in one go but if you start off doing things this way it will be better, hope this helps.

1
ekvalizer On

If you want to just close your port you can implement IDisposable interface in your SerialPortSettingView class like this. Each time you change DataContext from SerialPortSettingView your port will be closed.

public class SerialPortSettingView : IDisposable
{
    private FileStream _fileStream;

    public SerialPortSettingView()
    {
        _fileStream = new FileStream("somefile.txt", FileMode.Open);
    }

    public void Dispose()
    {
        _fileStream?.Close();
    }
}