在 WPF 中更改 DataContext/View 后保留数据

Data Retain After Changing DataContext/ Views in WPF

我是 WPF 的新手,想构建一个应用程序,它将与我的驱动程序进行串行通信,并且我可以从程序中为驱动程序设置值。

我已经成功制作了一个UI如图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 设置按钮是指向右上角的箭头(window 的关闭按钮下方),按下时我的 window 看起来像 this。

基本上我正在根据我按下的按钮更改 BIG RECTANGLE 内容(例如,单击蓝色视图时矩形为蓝色,矩形填充有红色和一个标签以及单击红色视图时更改标签的按钮)

所以现在我的问题是,在更改 BIG RECTANGLE 的内容后,我无法保留在此 BIG RECTANGLE 中设置的值].例如,当我按下设置按钮并更改 this 等设置时,我已准备好在 COM5 中进行通信,并且可以按下关闭端口的选项。现在在关闭端口之前,如果我通过按红色视图或蓝色视图更改 BIG RECTANGLE 的视图,然后在按下设置按钮之后,我就没有关闭端口的选项了,因为我之前已经打开了 com5 端口,所以当我尝试打开该端口时,它也会给我错误。

请帮我解决这个问题。我的 visual studio 解决方案资源管理器看起来像 this,我在按钮单击事件中的代码如下:

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

我的解决方案资源管理器看起来像 this

每次更改视图时,您都会创建一个新的 object 来将 DataContext 设置为,如果您将单个 object 保留为私有字段,则只需将 DataContext 设置为这些:

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

这样,当您在视图之间切换时,您将使用存储的版本,而当您更改值时,它们将存储在该视图中。

如果我正在执行此解决方案,我会将 ContentControl 更改为 TabControl(隐藏 headers),然后创建每个视图以及随附的 ViewModel 作为选项卡。然后,当每个点击事件被触发时,您只需设置 TabControl 的 .SelectedIndex 属性。我将创建一个 MainWindowViewModel 并在构造函数中将 MainWindow 的 DataContext 设置为此:

    private MainWindowViewModel = new MainWindowViewModel();

    public MainWindow()
    {
        DataContext = _mainWindowViewModel;
    }

并将所有逻辑放在 MainWindowViewModel 中(您需要使用命令)。使用代码隐藏并不是 WPF 的本意,您可以在此处阅读所有内容,并遵循一个很好的教程 - MVVM Tutorial

我不想让事情变得过于复杂,一次性给你塞满太多信息,但如果你开始这样做会更好,希望这会有所帮助。

如果你只想关闭你的端口,你可以像这样在你的 SerialPortSettingView class 中实现 IDisposable 接口。每次您从 SerialPortSettingView 更改 DataContext 时,您的端口将被关闭。

public class SerialPortSettingView : IDisposable
{
    private FileStream _fileStream;

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

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