нужно максимально оптимизировать код, потому что жрет очень много памяти

<Window x:Class="magnet.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:magnet"
        Title="Magnet File Previewer" Height="800" Width="1000">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <!-- Левая панель с кнопками -->
        <StackPanel Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="10">
            <Button Name="LoadTxtFilesButton" Width="180" Height="40" Click="LoadTxtFilesButton_Click" Margin="0,10,0,15">Загрузить .txt файлы</Button>
            <Button Name="LoadMagnetFilesButton" Width="180" Height="40" Click="LoadMagnetFilesButton_Click" Margin="0,0,0,15">Загрузить .magnet файлы</Button>
            <Button Name="CreateCombinedFileButton" Width="180" Height="40" Click="CreateCombinedFileButton_Click" Margin="0,0,0,15">Создать объединённый файл</Button>
            <Button Name="SaveProjectButton" Width="180" Height="40" Click="SaveProjectButton_Click" Margin="0,0,0,15">Сохранить проект</Button>
            <Button Name="LoadProjectButton" Width="180" Height="40" Click="LoadProjectButton_Click">Загрузить проект</Button>
        </StackPanel>
        <!-- Правая панель с списками файлов и предпросмотром -->
        <Grid Grid.Column="1" Margin="10">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="2*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <!-- Списки загруженных файлов -->
            <Grid Grid.Row="0" Margin="0,0,0,10">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <!-- Группа .txt файлов -->
                <GroupBox Header=".txt файлы" Grid.Column="0" Margin="0,0,5,0">
                    <ListView Name="TxtFilesListView" SelectionChanged="TxtFilesListView_SelectionChanged"
                              VirtualizingStackPanel.IsVirtualizing="True">
                        <ListView.View>
                            <GridView>
                                <GridViewColumn Header="Название файла" DisplayMemberBinding="{Binding FilePath}" Width="200"/>
                                <GridViewColumn Header="Строки для пропуска" Width="150">
                                    <GridViewColumn.CellTemplate>
                                        <DataTemplate>
                                            <TextBox Text="{Binding LinesToSkip, UpdateSourceTrigger=PropertyChanged}" Width="140"/>
                                        </DataTemplate>
                                    </GridViewColumn.CellTemplate>
                                </GridViewColumn>
                            </GridView>
                        </ListView.View>
                    </ListView>
                </GroupBox>
                <!-- Группа .magnet файлов -->
                <GroupBox Header=".magnet файлы" Grid.Column="1" Margin="5,0,0,0">
                    <ListView Name="MagnetFilesListView" SelectionChanged="MagnetFilesListView_SelectionChanged"
                              VirtualizingStackPanel.IsVirtualizing="True">
                        <ListView.View>
                            <GridView>
                                <GridViewColumn Header="Название файла" DisplayMemberBinding="{Binding FilePath}" Width="200"/>
                                <GridViewColumn Header="Строки для пропуска" Width="150">
                                    <GridViewColumn.CellTemplate>
                                        <DataTemplate>
                                            <TextBox Text="{Binding LinesToSkip, UpdateSourceTrigger=PropertyChanged}" Width="140"/>
                                        </DataTemplate>
                                    </GridViewColumn.CellTemplate>
                                </GridViewColumn>
                            </GridView>
                        </ListView.View>
                    </ListView>
                </GroupBox>
            </Grid>
            <!-- Поле ввода LinesToSkip и кнопка Обновить -->
            <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,0,10">
                <Label Content="Пропустить строк:" VerticalAlignment="Center"/>
                <TextBox Name="LinesToSkipTextBox" Width="60" Margin="5,0,0,0" Text="0" />
                <Button Content="Обновить" Click="UpdateLinesToSkip_Click" Margin="10,0,0,0" Width="80" />
            </StackPanel>
            <!-- Область предпросмотра файла -->
            <ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
                <DataGrid Name="PreviewDataGrid" IsReadOnly="True" 
                          AutoGenerateColumns="False" 
                          HeadersVisibility="Column" 
                          CanUserAddRows="False"
                          CanUserDeleteRows="False"
                          CanUserResizeColumns="True"
                          CanUserSortColumns="False"
                          FontFamily="Consolas"
                          FontSize="12"
                          EnableRowVirtualization="True"
                          EnableColumnVirtualization="True"
                          VirtualizingPanel.IsVirtualizing="True"
                          VirtualizingPanel.VirtualizationMode="Recycling"
                          ScrollViewer.CanContentScroll="True">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Столбец 1" Binding="{Binding Columns[0]}" Width="100"/>
                        <DataGridTextColumn Header="Столбец 2" Binding="{Binding Columns[1]}" Width="100"/>
                        <DataGridTextColumn Header="Столбец 3" Binding="{Binding Columns[2]}" Width="100"/>
                        <DataGridTextColumn Header="Столбец 4" Binding="{Binding Columns[3]}" Width="100"/>
                        <DataGridTextColumn Header="Столбец 5" Binding="{Binding Columns[4]}" Width="100"/>
                    </DataGrid.Columns>
                </DataGrid>
            </ScrollViewer>
            <!-- Таблица с обработанными файлами -->
            <GroupBox Grid.Row="3" Header="Обработанные файлы" Margin="0,10,0,0">
                <TabControl Name="ProcessedFilesTabControl">
                    <!-- Удалены настройки VirtualizationMode чтобы избежать ошибки XDG0066 -->
                </TabControl>
            </GroupBox>
        </Grid>
    </Grid>
</Window>

<Window x:Class="magnet.SelectFilesWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Выберите файлы для объединения" Height="400" Width="300">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ListBox Name="FilesListBox" SelectionMode="Extended" DisplayMemberPath="FilePath"
                 VirtualizingStackPanel.IsVirtualizing="True">
            <!-- VirtualizingStackPanel.VirtualizationMode="Recycling" удалено -->
        </ListBox>
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
            <Button Content="OK" Width="75" Click="OKButton_Click" Margin="0,0,10,0"/>
            <Button Content="Отмена" Width="75" Click="CancelButton_Click"/>
        </StackPanel>
    </Grid>
</Window>

using System.Collections.Generic;
using System.Windows;

namespace magnet
{
    public partial class SelectFilesWindow : Window
    {
        public List<FileSetting> SelectedFilesSettings { get; private set; } = new List<FileSetting>();
        private readonly int maxSelection;

        public SelectFilesWindow(IEnumerable<FileSetting> availableFiles, int maxSelection)
        {
            InitializeComponent();
            FilesListBox.ItemsSource = availableFiles;
            this.maxSelection = maxSelection;
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            if (FilesListBox.SelectedItems.Count != maxSelection)
            {
                MessageBox.Show($"Выберите ровно {maxSelection} файла(ов) для объединения.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            foreach (var item in FilesListBox.SelectedItems)
            {
                if (item is FileSetting fileSetting)
                {
                    SelectedFilesSettings.Add(fileSetting);
                }
            }

            DialogResult = true;
            Close();
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
            Close();
        }
    }
}

using System.Collections.Generic;
using System.ComponentModel;

namespace magnet
{
    public class ProjectModel : INotifyPropertyChanged
    {
        private List<FileSetting> txtFiles = new List<FileSetting>();
        private List<FileSetting> magnetFiles = new List<FileSetting>();

        public List<FileSetting> TxtFiles
        {
            get => txtFiles;
            set
            {
                if (txtFiles != value)
                {
                    txtFiles = value;
                    OnPropertyChanged(nameof(TxtFiles));
                }
            }
        }

        public List<FileSetting> MagnetFiles
        {
            get => magnetFiles;
            set
            {
                if (magnetFiles != value)
                {
                    magnetFiles = value;
                    OnPropertyChanged(nameof(MagnetFiles));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public class FileSetting : INotifyPropertyChanged
    {
        private string filePath;
        private int linesToSkip;

        public string FilePath
        {
            get => filePath;
            set
            {
                if (filePath != value)
                {
                    filePath = value;
                    OnPropertyChanged(nameof(FilePath));
                }
            }
        }

        public int LinesToSkip
        {
            get => linesToSkip;
            set
            {
                if (linesToSkip != value)
                {
                    linesToSkip = value;
                    OnPropertyChanged(nameof(LinesToSkip));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public class ProcessedFile
    {
        public string FileName { get; set; }
        public IEnumerable<ProcessedRow> Data { get; set; }
    }

    public class ProcessedRow : INotifyPropertyChanged
    {
        private string column2;
        private string column3;
        private string column4;
        private string column5;

        public string Column2
        {
            get => column2;
            set
            {
                if (column2 != value)
                {
                    column2 = value;
                    OnPropertyChanged(nameof(Column2));
                }
            }
        }

        public string Column3
        {
            get => column3;
            set
            {
                if (column3 != value)
                {
                    column3 = value;
                    OnPropertyChanged(nameof(Column3));
                }
            }
        }

        public string Column4
        {
            get => column4;
            set
            {
                if (column4 != value)
                {
                    column4 = value;
                    OnPropertyChanged(nameof(Column4));
                }
            }
        }

        public string Column5
        {
            get => column5;
            set
            {
                if (column5 != value)
                {
                    column5 = value;
                    OnPropertyChanged(nameof(Column5));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

using Microsoft.Win32;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace magnet
{
    public partial class MainWindow : Window
    {
        private ProjectModel currentProject = new ProjectModel();
        private FileSetting selectedFile = null;
        private const int MaxPreviewLines = 1000;

        public MainWindow()
        {
            InitializeComponent();
            TxtFilesListView.ItemsSource = currentProject.TxtFiles;
            MagnetFilesListView.ItemsSource = currentProject.MagnetFiles;
        }

        private async void LoadTxtFilesButton_Click(object sender, RoutedEventArgs e)
        {
            await LoadFilesAsync(".txt", currentProject.TxtFiles, TxtFilesListView);
        }

        private async void LoadMagnetFilesButton_Click(object sender, RoutedEventArgs e)
        {
            await LoadFilesAsync(".magnet", currentProject.MagnetFiles, MagnetFilesListView);
        }

        private async Task LoadFilesAsync(string extension, List<FileSetting> fileCollection, ListView listView)
        {
            OpenFileDialog dlg = new OpenFileDialog
            {
                Multiselect = true,
                Filter = $"Файлы {extension}|*{extension}"
            };

            bool? result = dlg.ShowDialog();

            if (result == true)
            {
                var newFiles = dlg.FileNames
                    .Where(filename => !fileCollection.Any(f => string.Equals(f.FilePath, filename, StringComparison.OrdinalIgnoreCase)))
                    .ToList();

                if (newFiles.Any())
                {
                    foreach (string filename in newFiles)
                    {
                        fileCollection.Add(new FileSetting { FilePath = filename, LinesToSkip = 0 });
                    }

                    listView.SelectedItem = fileCollection.Last();
                }
                else
                {
                    MessageBox.Show("Все выбранные файлы уже добавлены.", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
        }

        private async void TxtFilesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (TxtFilesListView.SelectedItem is FileSetting selected)
            {
                selectedFile = selected;
                LinesToSkipTextBox.Text = selected.LinesToSkip.ToString();
                MagnetFilesListView.SelectedItem = null;
                await PreviewFileAsync(selected);
            }
            else
            {
                ClearPreview();
            }
        }

        private async void MagnetFilesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (MagnetFilesListView.SelectedItem is FileSetting selected)
            {
                selectedFile = selected;
                LinesToSkipTextBox.Text = selected.LinesToSkip.ToString();
                TxtFilesListView.SelectedItem = null;
                await PreviewFileAsync(selected);
            }
            else
            {
                ClearPreview();
            }
        }

        private void ClearPreview()
        {
            selectedFile = null;
            PreviewDataGrid.ItemsSource = null;
            LinesToSkipTextBox.Text = "0";
        }

        private async Task PreviewFileAsync(FileSetting fileSetting)
        {
            if (!File.Exists(fileSetting.FilePath))
            {
                ClearPreview();
                MessageBox.Show($"Файл не найден: {fileSetting.FilePath}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            try
            {
                var data = new List<PreviewRow>();
                int maxColumns = 0;

                using (var reader = new StreamReader(fileSetting.FilePath))
                {
                    for (int i = 0; i < fileSetting.LinesToSkip; i++)
                    {
                        if (await reader.ReadLineAsync() == null)
                            break;
                    }

                    string line;
                    int count = 0;
                    while ((line = await reader.ReadLineAsync()) != null && count < MaxPreviewLines)
                    {
                        var columns = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (columns.Length > maxColumns)
                            maxColumns = columns.Length;

                        // Используем конструктор PreviewRow
                        data.Add(new PreviewRow(columns.ToList()));
                        count++;
                    }
                }

                Dispatcher.Invoke(() =>
                {
                    PreviewDataGrid.Columns.Clear();

                    for (int i = 0; i < maxColumns; i++)
                    {
                        PreviewDataGrid.Columns.Add(new DataGridTextColumn
                        {
                            Header = $"Столбец {i + 1}",
                            Binding = new System.Windows.Data.Binding($"Columns[{i}]"),
                            Width = 100
                        });
                    }

                    PreviewDataGrid.ItemsSource = data;
                    this.Title = $"Magnet File Previewer - {Path.GetFileName(fileSetting.FilePath)} (Предпросмотр {data.Count} строк)";
                });
            }
            catch (Exception ex)
            {
                ClearPreview();
                MessageBox.Show($"Ошибка при чтении файла: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private async void UpdateLinesToSkip_Click(object sender, RoutedEventArgs e)
        {
            if (selectedFile != null)
            {
                if (int.TryParse(LinesToSkipTextBox.Text, out int skip) && skip >= 0)
                {
                    selectedFile.LinesToSkip = skip;
                    await PreviewFileAsync(selectedFile);
                    RefreshListView(selectedFile);
                }
                else
                {
                    MessageBox.Show("Введите корректное неотрицательное число строк для пропуска.", "Ошибка ввода", MessageBoxButton.OK, MessageBoxImage.Warning);
                }
            }
            else
            {
                MessageBox.Show("Выберите файл для обновления.", "Предупреждение", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }

        private void RefreshListView(FileSetting file)
        {
            if (file.FilePath.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
            {
                var index = currentProject.TxtFiles.IndexOf(file);
                if (index >= 0)
                {
                    currentProject.TxtFiles[index] = file;
                    TxtFilesListView.Items.Refresh();
                }
            }
            else if (file.FilePath.EndsWith(".magnet", StringComparison.OrdinalIgnoreCase))
            {
                var index = currentProject.MagnetFiles.IndexOf(file);
                if (index >= 0)
                {
                    currentProject.MagnetFiles[index] = file;
                    MagnetFilesListView.Items.Refresh();
                }
            }
        }

        private void SaveProjectButton_Click(object sender, RoutedEventArgs e)
        {
            if (!currentProject.TxtFiles.Any() && !currentProject.MagnetFiles.Any())
            {
                MessageBox.Show("Нет файлов для сохранения проекта.", "Предупреждение", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            SaveFileDialog dlg = new SaveFileDialog
            {
                Filter = "Magnet Project Files (*.magn)|*.magn",
                DefaultExt = "magn",
                FileName = "project.magn"
            };

            bool? result = dlg.ShowDialog();

            if (result == true)
            {
                try
                {
                    string json = JsonConvert.SerializeObject(currentProject, Formatting.Indented);
                    File.WriteAllText(dlg.FileName, json);
                    MessageBox.Show("Проект успешно сохранён!", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Ошибка при сохранении проекта: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        private async void LoadProjectButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog
            {
                Filter = "Magnet Project Files (*.magn)|*.magn",
                DefaultExt = "magn"
            };

            bool? result = dlg.ShowDialog();

            if (result == true)
            {
                try
                {
                    string json = await File.ReadAllTextAsync(dlg.FileName);
                    ProjectModel loadedProject = JsonConvert.DeserializeObject<ProjectModel>(json);

                    if (loadedProject != null)
                    {
                        currentProject.TxtFiles = loadedProject.TxtFiles ?? new List<FileSetting>();
                        currentProject.MagnetFiles = loadedProject.MagnetFiles ?? new List<FileSetting>();

                        TxtFilesListView.ItemsSource = currentProject.TxtFiles;
                        MagnetFilesListView.ItemsSource = currentProject.MagnetFiles;

                        TxtFilesListView.Items.Refresh();
                        MagnetFilesListView.Items.Refresh();

                        ClearPreview();

                        MessageBox.Show("Проект успешно загружен!", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
                    }
                    else
                    {
                        MessageBox.Show("Не удалось загрузить проект.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Ошибка при загрузке проекта: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        private async void CreateCombinedFileButton_Click(object sender, RoutedEventArgs e)
        {
            if (currentProject.TxtFiles.Count < 2)
            {
                MessageBox.Show("Необходимо загрузить минимум два .txt файла для объединения.", "Предупреждение", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            SelectFilesWindow selectFilesWindow = new SelectFilesWindow(currentProject.TxtFiles, 2);
            if (selectFilesWindow.ShowDialog() == true)
            {
                List<FileSetting> selectedTxtFiles = selectFilesWindow.SelectedFilesSettings;

                if (selectedTxtFiles.Count != 2)
                {
                    MessageBox.Show("Выберите ровно два файла для объединения.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                try
                {
                    string combinedFileName = $"Combined_{DateTime.Now:yyyyMMdd_HHmmss}.magn";
                    ProcessedFile processedFile = new ProcessedFile
                    {
                        FileName = combinedFileName,
                        Data = ReadAndCombineFiles(selectedTxtFiles)
                    };

                    if (!processedFile.Data.Any())
                    {
                        MessageBox.Show("Объединённые файлы не содержат данных для объединения.", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
                        return;
                    }

                    AddProcessedFileTab(processedFile);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Ошибка при объединении файлов: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        private IEnumerable<ProcessedRow> ReadAndCombineFiles(List<FileSetting> files)
        {
            foreach (var file in files)
            {
                using (var reader = new StreamReader(file.FilePath))
                {
                    // Пропуск строк
                    for (int i = 0; i < file.LinesToSkip; i++)
                    {
                        if (reader.ReadLine() == null)
                            break;
                    }

                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        if (string.IsNullOrWhiteSpace(line))
                            continue;

                        string[] columns = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        if (columns.Length < 5)
                        {
                            MessageBox.Show($"Файл {file.FilePath} содержит строку с недостаточным количеством столбцов: {line}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                            yield break;
                        }

                        string formattedTime = "00:00:00";
                        if (double.TryParse(columns[4], out double originalValue))
                        {
                            double divided = originalValue / 24.0;
                            TimeSpan time = TimeSpan.FromHours(divided);
                            formattedTime = time.ToString(@"hh\:mm\:ss");
                        }

                        yield return new ProcessedRow
                        {
                            Column2 = columns[1],
                            Column3 = columns[2],
                            Column4 = columns[3],
                            Column5 = formattedTime
                        };
                    }
                }
            }
        }

        private void AddProcessedFileTab(ProcessedFile processedFile)
        {
            DataGrid dataGrid = new DataGrid
            {
                AutoGenerateColumns = false,
                IsReadOnly = true,
                CanUserAddRows = false,
                ItemsSource = processedFile.Data,
                Margin = new Thickness(5),
                EnableRowVirtualization = true,
                EnableColumnVirtualization = true
            };

            dataGrid.Columns.Add(new DataGridTextColumn { Header = "Столбец 1", Binding = new System.Windows.Data.Binding("Column2"), Width = 150 });
            dataGrid.Columns.Add(new DataGridTextColumn { Header = "Столбец 2", Binding = new System.Windows.Data.Binding("Column3"), Width = 150 });
            dataGrid.Columns.Add(new DataGridTextColumn { Header = "Столбец 3", Binding = new System.Windows.Data.Binding("Column4"), Width = 150 });
            dataGrid.Columns.Add(new DataGridTextColumn { Header = "Столбец 4", Binding = new System.Windows.Data.Binding("Column5"), Width = 100 });

            Button saveButton = new Button
            {
                Content = "Сохранить файл",
                Width = 120,
                Height = 30,
                Margin = new Thickness(5)
            };
            saveButton.Click += (s, e) => SaveProcessedFile(processedFile);

            StackPanel stackPanel = new StackPanel();
            stackPanel.Children.Add(dataGrid);
            stackPanel.Children.Add(saveButton);

            TabItem tabItem = new TabItem
            {
                Header = processedFile.FileName,
                Content = stackPanel
            };

            ProcessedFilesTabControl.Items.Add(tabItem);
            ProcessedFilesTabControl.SelectedItem = tabItem;
        }

        private async void SaveProcessedFile(ProcessedFile processedFile)
        {
            SaveFileDialog dlg = new SaveFileDialog
            {
                Filter = "Magnet Files (*.magn)|*.magn",
                DefaultExt = "magn",
                FileName = processedFile.FileName
            };

            bool? result = dlg.ShowDialog();

            if (result == true)
            {
                try
                {
                    using (var writer = new StreamWriter(dlg.FileName))
                    {
                        await writer.WriteLineAsync("Столбец 1\tСтолбец 2\tСтолбец 3\tСтолбец 4");

                        foreach (var row in processedFile.Data)
                        {
                            string line = $"{row.Column2}\t{row.Column3}\t{row.Column4}\t{row.Column5}";
                            await writer.WriteLineAsync(line);
                        }
                    }

                    MessageBox.Show("Файл успешно сохранён!", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Ошибка при сохранении файла: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
    }

    public class PreviewRow : INotifyPropertyChanged
    {
        private readonly List<string> columns;

        public PreviewRow(List<string> columns)
        {
            this.columns = columns;
        }

        public List<string> Columns => columns;

        public event PropertyChangedEventHandler PropertyChanged;
    }
}