refactor mvvm, add datacontext

This commit is contained in:
2025-12-10 21:33:06 +05:00
parent b6ddadc6d3
commit 5479da163e
5 changed files with 566 additions and 621 deletions

View File

@@ -8,6 +8,10 @@
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>

View File

@@ -1,77 +1,66 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
namespace CodeContextGenerator.Models
{
public class FileItem : INotifyPropertyChanged
public partial class FileItem : ObservableObject
{
public string Name { get; set; }
public string FullName { get; set; }
public bool IsDirectory { get; set; }
public ObservableCollection<FileItem> Children { get; set; } = new ObservableCollection<FileItem>();
public FileItem Parent { get; set; }
[ObservableProperty]
private string? name;
private bool? _isSelected;
public bool? IsSelected
[ObservableProperty]
private string? fullName;
[ObservableProperty]
private bool isDirectory;
[ObservableProperty]
private bool? isSelected;
[ObservableProperty]
private FileItem? parent;
public ObservableCollection<FileItem> Children { get; } = new ObservableCollection<FileItem>();
/*partial void OnIsSelectedChanged(bool? oldValue, bool? newValue)
{
get => _isSelected;
set
if (newValue.HasValue)
{
if (_isSelected != value)
{
_isSelected = value;
OnPropertyChanged();
UpdateChildrenSelection(newValue.Value);
}
UpdateParentSelection();
}*/
// Если это директория и установлено конкретное значение (не null), применяем ко всем детям
if (IsDirectory && value.HasValue)
private void UpdateChildrenSelection(bool value)
{
if (!IsDirectory) return;
foreach (var child in Children)
{
child.IsSelected = value.Value;
child.IsSelected = value;
}
}
}
}
}
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void UpdateParentSelection()
{
if (Parent == null) return;
var children = Parent.Children.ToList();
var children = Parent.Children;
var allSelected = children.All(c => c.IsSelected == true);
var noneSelected = children.All(c => c.IsSelected == false);
var hasIndeterminate = children.Any(c => c.IsSelected == null);
// Если есть дети с null - устанавливаем null
bool hasIndeterminate = children.Any(c => c.IsSelected == null);
if (hasIndeterminate)
{
Parent.IsSelected = null;
}
else if (allSelected)
{
Parent.IsSelected = true;
}
else if (noneSelected)
{
Parent.IsSelected = false;
}
else
{
Parent.IsSelected = null;
}
Parent.IsSelected = hasIndeterminate ? null : (allSelected ? true : (noneSelected ? false : null));
Parent.UpdateParentSelection();
}
public void ClearSelection()
{
IsSelected = false;
foreach (var child in Children)
{
child.ClearSelection();
}
}
}
}

View File

@@ -1,162 +1,89 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
using Microsoft.Win32;
using CodeContextGenerator.Models;
using CodeContextGenerator.Models;
using CodeContextGenerator.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Win32;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace CodeContextGenerator.ViewModels
namespace CodeContextGenerator.ViewModels;
public partial class MainViewModel : ObservableObject, INotifyPropertyChanged
{
public class MainViewModel : INotifyPropertyChanged
{
private FileItem _rootDirectory;
private string _selectedProjectFilePath;
private bool _isProcessing;
[ObservableProperty]
private FileItem? _rootDirectory = new();
[ObservableProperty]
private string _selectedProjectFilePath = string.Empty;
[ObservableProperty]
private bool _isProcessing = false;
[ObservableProperty]
private int _progressValue;
private string _progressText;
private CancellationTokenSource _cancellationTokenSource;
private string _lastProjectPath;
[ObservableProperty]
private string _progressText = string.Empty;
[ObservableProperty]
private string? _lastProjectPath = string.Empty;
[ObservableProperty]
private bool _isProjectLoaded;
public FileItem RootDirectory
{
get => _rootDirectory;
set
{
_rootDirectory = value;
OnPropertyChanged();
}
}
public string SelectedProjectFilePath
{
get => _selectedProjectFilePath;
set
{
_selectedProjectFilePath = value;
OnPropertyChanged();
}
}
public bool IsProcessing
{
get => _isProcessing;
set
{
_isProcessing = value;
OnPropertyChanged();
OnPropertyChanged(nameof(CanSelectFolder));
OnPropertyChanged(nameof(CanGenerate));
}
}
public int ProgressValue
{
get => _progressValue;
set
{
_progressValue = value;
OnPropertyChanged();
}
}
public string ProgressText
{
get => _progressText;
set
{
_progressText = value;
OnPropertyChanged();
}
}
public bool IsProjectLoaded
{
get => _isProjectLoaded;
set
{
_isProjectLoaded = value;
OnPropertyChanged();
}
}
private CancellationTokenSource _cancellationTokenSource = new();
public bool CanSelectFolder => !IsProcessing;
public bool CanGenerate => !IsProcessing && IsProjectLoaded && HasSelectedFiles(RootDirectory);
public ICommand SelectProjectFileCommand { get; }
public ICommand GenerateCommand { get; }
public ICommand CancelCommand { get; }
public ICommand ExitCommand { get; }
//public ICommand SelectProjectFileCommand { get; }
//public ICommand GenerateCommand { get; }
//public ICommand CancelCommand { get; }
//public ICommand ExitCommand { get; }
public MainViewModel()
{
SelectProjectFileCommand = new RelayCommand(SelectProjectFileAsync);
GenerateCommand = new RelayCommand(GenerateFileAsync, _ => CanGenerate);
CancelCommand = new RelayCommand(CancelProcessing, _ => IsProcessing);
ExitCommand = new RelayCommand(_ => Application.Current.Shutdown());
//ExitCommand = new RelayCommand(_ => Application.Current.Shutdown());
LoadSettings();
}
private bool HasSelectedFiles(FileItem item)
{
if (item == null) return false;
if (item.IsSelected == true && !item.IsDirectory)
return true;
foreach (var child in item.Children)
{
if (HasSelectedFiles(child))
return true;
if (item.IsSelected == true && !item.IsDirectory) return true;
return item.Children.Any(HasSelectedFiles);
}
return false;
//[RelayCommand(CanExecute = nameof(CanSelectFolder))]
[RelayCommand(CanExecute = nameof(CanSelectFolder))]
private void Exit()
{
Application.Current.Shutdown();
}
private async void SelectProjectFileAsync(object parameter)
//[RelayCommand(CanExecute = nameof(CanSelectFolder))]
[RelayCommand(CanExecute = nameof(CanGenerate))]
private void Cancel()
{
if (!CanSelectFolder) return;
CancelProcessing();
}
[RelayCommand(CanExecute = nameof(CanSelectFolder))]
private async Task SelectProjectFileAsync()
{
var dialog = new OpenFileDialog
{
Title = "Выберите файл решения или проекта",
CheckFileExists = true,
CheckPathExists = true,
Filter = "Файлы решений Visual Studio (*.sln)|*.sln|Файлы проектов C# (*.csproj)|*.csproj|Все поддерживаемые файлы (*.sln;*.csproj)|*.sln;*.csproj|Все файлы (*.*)|*.*",
Multiselect = false
Filter = "Файлы решений (*.sln)|*.sln|Файлы проектов (*.csproj)|*.csproj|Все поддерживаемые (*.sln;*.csproj)|*.sln;*.csproj|Все файлы (*.*)|*.*",
InitialDirectory = !string.IsNullOrEmpty(LastProjectPath) && Directory.Exists(LastProjectPath) ? LastProjectPath : null
};
if (!string.IsNullOrEmpty(_lastProjectPath) && Directory.Exists(_lastProjectPath))
{
dialog.InitialDirectory = _lastProjectPath;
}
if (dialog.ShowDialog() != true) return;
bool? result = dialog.ShowDialog();
if (result == true)
{
string selectedFilePath = dialog.FileName;
string projectDirectory = Path.GetDirectoryName(selectedFilePath);
if (!string.IsNullOrEmpty(projectDirectory))
{
_lastProjectPath = projectDirectory;
SelectedProjectFilePath = dialog.FileName;
LastProjectPath = Path.GetDirectoryName(SelectedProjectFilePath);
SaveSettings();
SelectedProjectFilePath = selectedFilePath;
IsProjectLoaded = false;
await LoadProjectAsync(selectedFilePath);
}
}
await LoadProjectAsync(SelectedProjectFilePath);
}
private async Task LoadProjectAsync(string projectFilePath)
@@ -167,9 +94,7 @@ namespace CodeContextGenerator.ViewModels
try
{
string projectDirectory = Path.GetDirectoryName(projectFilePath);
SelectedProjectFilePath = projectFilePath;
string? projectDirectory = Path.GetDirectoryName(projectFilePath);
var progress = new Progress<int>(value =>
{
ProgressValue = value;
@@ -178,7 +103,6 @@ namespace CodeContextGenerator.ViewModels
_cancellationTokenSource = new CancellationTokenSource();
// Определяем тип файла
if (projectFilePath.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))
{
await LoadSolutionAsync(projectFilePath, progress, _cancellationTokenSource.Token);
@@ -213,7 +137,7 @@ namespace CodeContextGenerator.ViewModels
{
try
{
string solutionDirectory = Path.GetDirectoryName(solutionPath);
string? solutionDirectory = Path.GetDirectoryName(solutionPath);
var solutionProjects = ParseSolutionProjects(solutionPath);
var solutionItem = new FileItem
@@ -233,8 +157,8 @@ namespace CodeContextGenerator.ViewModels
if (File.Exists(projectPath))
{
string projectDir = Path.GetDirectoryName(projectPath);
string projectName = Path.GetFileName(projectDir);
string? projectDir = Path.GetDirectoryName(projectPath);
string? projectName = Path.GetFileName(projectDir);
var projectItem = new FileItem
{
@@ -268,18 +192,18 @@ namespace CodeContextGenerator.ViewModels
}
}
private List<string> ParseSolutionProjects(string solutionPath)
private static List<string> ParseSolutionProjects(string solutionPath)
{
var projects = new List<string>();
try
{
string solutionDirectory = Path.GetDirectoryName(solutionPath);
string? solutionDirectory = Path.GetDirectoryName(solutionPath);
foreach (string line in File.ReadAllLines(solutionPath))
{
if (line.Trim().StartsWith("Project(", StringComparison.OrdinalIgnoreCase))
{
var parts = line.Split(new[] { '"' }, StringSplitOptions.RemoveEmptyEntries);
var parts = line.Split(['"'], StringSplitOptions.RemoveEmptyEntries);
if (parts.Length >= 3)
{
string relativePath = parts[2].Trim();
@@ -326,7 +250,7 @@ namespace CodeContextGenerator.ViewModels
}
}
private void ClearAllSelections(FileItem item)
private static void ClearAllSelections(FileItem item)
{
item.IsSelected = false;
foreach (var child in item.Children)
@@ -335,12 +259,10 @@ namespace CodeContextGenerator.ViewModels
}
}
private async void GenerateFileAsync(object parameter)
[RelayCommand(CanExecute = nameof(CanGenerate))]
private async Task GenerateFileAsync()
{
if (!CanGenerate || RootDirectory == null) return;
var selectedFiles = GetSelectedFiles(RootDirectory);
if (selectedFiles.Count == 0)
{
MessageBox.Show("Пожалуйста, выберите хотя бы один файл для обработки.", "Предупреждение", MessageBoxButton.OK, MessageBoxImage.Warning);
@@ -352,22 +274,13 @@ namespace CodeContextGenerator.ViewModels
Title = "Сохранить контекстный файл",
Filter = "Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*",
FileName = $"{Path.GetFileNameWithoutExtension(SelectedProjectFilePath)}_context.txt",
DefaultExt = ".txt"
DefaultExt = ".txt",
InitialDirectory = LastProjectPath
};
if (!string.IsNullOrEmpty(_lastProjectPath) && Directory.Exists(_lastProjectPath))
{
saveDialog.InitialDirectory = _lastProjectPath;
}
if (saveDialog.ShowDialog() != true) return;
bool? result = saveDialog.ShowDialog();
if (result == true)
{
IsProcessing = true;
ProgressText = "Генерация контекстного файла...";
ProgressValue = 0;
try
{
_cancellationTokenSource = new CancellationTokenSource();
@@ -378,7 +291,6 @@ namespace CodeContextGenerator.ViewModels
});
await GenerateContextFileAsync(selectedFiles, saveDialog.FileName, progress, _cancellationTokenSource.Token);
MessageBox.Show($"Файл успешно создан:\n{saveDialog.FileName}", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (OperationCanceledException)
@@ -387,7 +299,7 @@ namespace CodeContextGenerator.ViewModels
}
catch (IOException ex)
{
MessageBox.Show($"Ошибка доступа к файлу: {ex.Message}\nПожалуйста, закройте файлы или предоставьте необходимые права доступа.", "Ошибка доступа", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show($"Ошибка доступа к файлу: {ex.Message}", "Ошибка доступа", MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (Exception ex)
{
@@ -398,7 +310,6 @@ namespace CodeContextGenerator.ViewModels
IsProcessing = false;
}
}
}
private List<string> GetSelectedFiles(FileItem rootItem)
{
@@ -407,7 +318,7 @@ namespace CodeContextGenerator.ViewModels
return selectedFiles;
}
private void CollectSelectedFiles(FileItem item, List<string> selectedFiles)
private static void CollectSelectedFiles(FileItem item, List<string> selectedFiles)
{
if (item.IsDirectory)
{
@@ -434,9 +345,9 @@ namespace CodeContextGenerator.ViewModels
try
{
string projectDir = Path.GetDirectoryName(SelectedProjectFilePath);
string relativePath = Path.GetRelativePath(projectDir, filePath);
string fileContent = await File.ReadAllTextAsync(filePath, Encoding.UTF8);
string? projectDir = Path.GetDirectoryName(SelectedProjectFilePath);
string? relativePath = Path.GetRelativePath(projectDir, filePath);
string? fileContent = await File.ReadAllTextAsync(filePath, Encoding.UTF8);
// Обработка комментариев
fileContent = FileProcessorService.ProcessFileContent(fileContent, Path.GetFileName(filePath));
@@ -461,7 +372,8 @@ namespace CodeContextGenerator.ViewModels
await File.WriteAllTextAsync(outputPath, outputContent.ToString(), encoding);
}
private void CancelProcessing(object parameter)
[RelayCommand]
private void CancelProcessing()
{
_cancellationTokenSource?.Cancel();
}
@@ -470,11 +382,11 @@ namespace CodeContextGenerator.ViewModels
{
try
{
_lastProjectPath = Properties.Settings.Default.LastProjectPath;
LastProjectPath = Properties.Settings.Default.LastProjectPath;
}
catch
{
_lastProjectPath = null;
LastProjectPath = string.Empty;
}
}
@@ -482,25 +394,23 @@ namespace CodeContextGenerator.ViewModels
{
try
{
Properties.Settings.Default.LastProjectPath = _lastProjectPath;
Properties.Settings.Default.LastProjectPath = LastProjectPath;
Properties.Settings.Default.Save();
}
catch
{
// Игнорируем ошибки сохранения настроек
}
catch { }
}
public event PropertyChangedEventHandler? PropertyChanged;
/*public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}*/
}
public class RelayCommand : ICommand
{
/*
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
@@ -518,5 +428,4 @@ namespace CodeContextGenerator.ViewModels
public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
}
}
}*/

View File

@@ -1,68 +1,95 @@
<Window x:Class="CodeContextGenerator.Views.MainWindow"
<Window
x:Class="CodeContextGenerator.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CodeContextGenerator.Views"
mc:Ignorable="d"
Title="Code Context Generator" Height="600" Width="800"
WindowStartupLocation="CenterScreen">
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodels="clr-namespace:CodeContextGenerator.ViewModels"
Title="Code Context Generator"
Width="800"
Height="600"
d:DataContext="{d:DesignInstance Type=viewmodels:MainViewModel}"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="IsExpanded" Value="True" />
<Setter Property="Focusable" Value="False" />
</Style>
<Style TargetType="Button">
<Setter Property="Padding" Value="10,5"/>
<Setter Property="Margin" Value="5,0"/>
<Setter Property="Padding" Value="10,5" />
<Setter Property="Margin" Value="5,0" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Window.Resources>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Выберите файл решения (.sln) или проекта (.csproj):" FontWeight="Bold" Margin="0,0,0,5"/>
<TextBlock
Grid.Row="0"
Margin="0,0,0,5"
FontWeight="Bold"
Text="Выберите файл решения (.sln) или проекта (.csproj):" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,0,10">
<Button Content="Выбрать файл..."
<StackPanel
Grid.Row="1"
Margin="0,0,0,10"
Orientation="Horizontal">
<Button
Width="120"
Command="{Binding SelectProjectFileCommand}"
IsEnabled="{Binding CanSelectFolder}"
Width="120"/>
<TextBlock Text="{Binding SelectedProjectFilePath}"
VerticalAlignment="Center"
TextWrapping="Wrap"
Content="Выбрать файл..."
IsEnabled="{Binding CanSelectFolder}" />
<TextBlock
MaxWidth="600"
Margin="10,0,0,0"/>
Margin="10,0,0,0"
VerticalAlignment="Center"
Text="{Binding SelectedProjectFilePath}"
TextWrapping="Wrap" />
</StackPanel>
<Border Grid.Row="2" BorderBrush="Gray" BorderThickness="1" CornerRadius="4" Padding="5"
<Border
Grid.Row="2"
Padding="5"
BorderBrush="Gray"
BorderThickness="1"
CornerRadius="4"
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}}">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">
<TreeView x:Name="ProjectTree" ItemsSource="{Binding RootDirectory.Children}"
<ScrollViewer
HorizontalScrollBarVisibility="Auto"
PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"
VerticalScrollBarVisibility="Auto">
<TreeView
x:Name="ProjectTree"
ItemsSource="{Binding RootDirectory.Children}"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" MinHeight="24">
<CheckBox IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}"
IsThreeState="True"
VerticalAlignment="Center" Margin="2,0,5,0"
Click="CheckBox_Click"/>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"
ToolTip="{Binding FullName}"/>
<StackPanel MinHeight="24" Orientation="Horizontal">
<CheckBox
Margin="2,0,5,0"
VerticalAlignment="Center"
Click="CheckBox_Click"
IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}"
IsThreeState="True" />
<TextBlock
VerticalAlignment="Center"
Text="{Binding Name}"
ToolTip="{Binding FullName}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
@@ -70,27 +97,49 @@
</ScrollViewer>
</Border>
<TextBlock Grid.Row="2" Text="Проект еще не загружен. Выберите файл решения или проекта."
HorizontalAlignment="Center" VerticalAlignment="Center"
Foreground="Gray" FontSize="14"
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=Collapsed}"/>
<TextBlock
Grid.Row="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
Foreground="Gray"
Text="Проект еще не загружен. Выберите файл решения или проекта."
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=Collapsed}" />
<ProgressBar Grid.Row="3" Value="{Binding ProgressValue}" Height="20" Margin="0,10,0,10"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Grid.Row="3" Text="{Binding ProgressText}" HorizontalAlignment="Center"
VerticalAlignment="Center" FontWeight="Bold"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<StackPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
<Button Content="Отмена" Command="{Binding CancelCommand}"
<ProgressBar
Grid.Row="3"
Height="20"
Margin="0,10,0,10"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}"
Background="#FFDC3545" Foreground="White"/>
<Button Content="Закрыть" Command="{Binding ExitCommand}"/>
<Button Content="Сформировать" Command="{Binding GenerateCommand}"
Value="{Binding ProgressValue}" />
<TextBlock
Grid.Row="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding ProgressText}"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}" />
<StackPanel
Grid.Row="4"
Margin="0,10,0,0"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button
Background="#FFDC3545"
Command="{Binding CancelCommand}"
Content="Отмена"
Foreground="White"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}" />
<Button Command="{Binding ExitCommand}" Content="Закрыть" />
<Button
Background="#FF28A745"
Command="{Binding GenerateFileCommand}"
Content="Сформировать"
Foreground="White"
IsEnabled="{Binding CanGenerate}"
Background="#FF28A745" Foreground="White"
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}}"/>
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}}" />
</StackPanel>
</Grid>
</Window>

View File

@@ -4,13 +4,14 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace CodeContextGenerator.Views
namespace CodeContextGenerator.Views;
public partial class MainWindow : Window
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
@@ -26,15 +27,8 @@ namespace CodeContextGenerator.Views
{
if (sender is CheckBox checkBox && checkBox.DataContext is FileItem fileItem)
{
// Принудительно обновляем состояние детей при клике
if (fileItem.IsDirectory && checkBox.IsChecked.HasValue)
{
foreach (var child in fileItem.Children)
{
child.IsSelected = checkBox.IsChecked;
}
}
}
// Синхронизация состояния чекбокса с ViewModel
fileItem.IsSelected = checkBox.IsChecked;
}
}
}