Загрузка данных


Ссылку на system.web.extension
L.get – вывод. DataGet с value get set
   MainApi:
DataGet data;
    public _mainAPI() => InitializeComponent();
    private async void Get(object sender, RoutedEventArgs e) {
        try {
            data = new JavaScriptSerializer().Deserialize<DataGet>(
                await new HttpClient().GetStringAsync("http://localhost:4444/TransferSimulator/fullName"));
            lGet.Content = data?.Value; }
        catch { MessageBox.Show("Ошибка API"); } }
    private void Set(object sender, RoutedEventArgs e) =>
        lSet.Content = data?.Value == null ? "Нет данных" : new Regex(@"тут").IsMatch(data.Value) ?
 "ФИО Содержит запрещенные символы" : "Валидация прошла успешно";

Текст:
(@"[^а-яА-ЯёЁ\s]"
Номер:
@"^\+7 \d{3} \d{3}-\d{2}-\d{2}$"
Почта:
@"^[^@\s]+@[^@\s]+\.[^@\s]+$"


main 

        <StackPanel Orientation="Horizontal" Grid.Row="0" Margin="0,0,0,10">
            <TextBlock Text="Поиск: " VerticalAlignment="Center"/>
            <TextBox Name="TbFind" Width="150" TextChanged="UpdateGrid"/>
            <TextBlock Text=" Сортировка: " VerticalAlignment="Center"/>
            <ComboBox Name="CbSort" Width="120" SelectionChanged="UpdateGrid">
                <ComboBoxItem Content="Без сортировки"/>
                <ComboBoxItem Content="Цена ↑"/>
                <ComboBoxItem Content="Цена ↓"/>
            </ComboBox>
        </StackPanel>

        <DataGrid Name="DgData" Grid.Row="1" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single">
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsActive}" Value="False">
                            <Setter Property="Background" Value="LightGray"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.RowStyle>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Название" Binding="{Binding Title}" Width="*"/>
                <DataGridTextColumn Header="Категория" Binding="{Binding TypeName}"/>
                <DataGridTextColumn Header="Цена" Binding="{Binding Cost, StringFormat=N2}"/>
            </DataGrid.Columns>
        </DataGrid>

        <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,10,0,0">
            <TextBlock Name="TbCount" VerticalAlignment="Center" Width="150"/>
            <Button Name="BtnAdd" Content="Добавить" Click="BtnAdd_Click" Margin="5,0"/>
            <Button Name="BtnEdit" Content="Изменить" Click="BtnEdit_Click" Margin="5,0"/>
            <Button Name="BtnDel" Content="Удалить" Click="BtnDel_Click" Margin="5,0"/>
        </StackPanel>
    </Grid>

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            if (Helper.RoleID != 1) { BtnAdd.Visibility = Visibility.Collapsed; BtnEdit.Visibility = Visibility.Collapsed; BtnDel.Visibility = Visibility.Collapsed; }
            UpdateGrid(null, null);
        }

        void UpdateGrid(object sender, RoutedEventArgs e)
        {
            if (DgData == null) return;
            string sql = $"SELECT i.ID, i.Title, i.Cost, i.IsActive, t.Title as TypeName FROM Items i JOIN Types t ON i.TypeID = t.ID WHERE i.Title LIKE N'%{TbFind.Text}%'";
            if (CbSort.SelectedIndex == 1) sql += " ORDER BY i.Cost ASC";
            if (CbSort.SelectedIndex == 2) sql += " ORDER BY i.Cost DESC";

            var dt = Helper.Get(sql);
            DgData.ItemsSource = dt.DefaultView;
            TbCount.Text = $"Записей: {dt.Rows.Count} из {Helper.Get("SELECT ID FROM Items").Rows.Count}";
        }

        private void BtnAdd_Click(object sender, RoutedEventArgs e) { new EditWindow(0).ShowDialog(); UpdateGrid(null, null); }

        private void BtnEdit_Click(object sender, RoutedEventArgs e)
        {
            if (DgData.SelectedItem is DataRowView r) { new EditWindow((int)r["ID"]).ShowDialog(); UpdateGrid(null, null); }
        }

        private void BtnDel_Click(object sender, RoutedEventArgs e)
        {
            if (DgData.SelectedItem is DataRowView r && MessageBox.Show("Удалить?", "!", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                Helper.Exec($"DELETE FROM Items WHERE ID={r["ID"]}"); UpdateGrid(null, null);
            }
        }


login 

    <!-- Группировка элементов ввода (требование КОД) -->
    <GroupBox Grid.Row="1" Header="Данные учетной записи" Margin="0,0,0,15" Padding="10">
        <StackPanel>
            <TextBlock Text="Логин:"/>
            <TextBox Name="LoginTextBox" TabIndex="1" Margin="0,5,0,10"/>

            <TextBlock Text="Пароль:"/>
            <PasswordBox Name="UserPasswordBox" TabIndex="2" Margin="0,5,0,5"/>
        </StackPanel>
    </GroupBox>

    <!-- Капча Пазл (Скрыта по умолчанию) -->
    <GroupBox Name="CaptchaGroupBox" Grid.Row="2" Header="Соберите пазл" Visibility="Collapsed" Margin="0,0,0,15">
        <UniformGrid Columns="2" Rows="2" Width="140" Height="140" Margin="5" HorizontalAlignment="Center">
            <!-- RenderTransformOrigin позволяет крутить ровно вокруг центра (0.5, 0.5) -->
            <Image Name="CaptchaImage1" Source="/Images/1.png" MouseLeftButtonDown="CaptchaImage_MouseLeftButtonDown" RenderTransformOrigin="0.5,0.5" Cursor="Hand" Stretch="Fill"/>
            <Image Name="CaptchaImage2" Source="/Images/2.png" MouseLeftButtonDown="CaptchaImage_MouseLeftButtonDown" RenderTransformOrigin="0.5,0.5" Cursor="Hand" Stretch="Fill"/>
            <Image Name="CaptchaImage3" Source="/Images/3.png" MouseLeftButtonDown="CaptchaImage_MouseLeftButtonDown" RenderTransformOrigin="0.5,0.5" Cursor="Hand" Stretch="Fill"/>
            <Image Name="CaptchaImage4" Source="/Images/4.png" MouseLeftButtonDown="CaptchaImage_MouseLeftButtonDown" RenderTransformOrigin="0.5,0.5" Cursor="Hand" Stretch="Fill"/>
        </UniformGrid>
    </GroupBox>

    <StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Center">
        <Button Name="LoginButton" Content="Войти" Width="100" Margin="5" TabIndex="3" Click="LoginButton_Click" Background="#FFD5E8D4"/>
        <Button Name="CancelButton" Content="Отмена" Width="100" Margin="5" TabIndex="4" Click="CancelButton_Click" Background="#FFF8CECC"/>
    </StackPanel>
</Grid>

    public partial class LoginWindow : Window
    {
        private int _failedAttempts = 0; // Счетчик неудачных попыток

        public LoginWindow()
        {
            InitializeComponent();
        }

        private void LoginButton_Click(object sender, RoutedEventArgs e)
        {
            string userLogin = LoginTextBox.Text.Trim();
            string userPassword = UserPasswordBox.Password.Trim();

            // 1. Проверка на пустые поля (Обработка ошибок пользователя)
            if (string.IsNullOrEmpty(userLogin) || string.IsNullOrEmpty(userPassword))
            {
                MessageBox.Show("Поля 'Логин' и 'Пароль' обязательны для заполнения.",
                                "Внимание", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            // 2. Проверка капчи (если она видима)
            if (CaptchaGroupBox.Visibility == Visibility.Visible)
            {
                bool isPuzzleSolved = CheckPuzzleState();

                if (isPuzzleSolved == false)
                {
                    HandleLoginFailure("Пазл собран неверно. Попробуйте еще раз.");
                    return;
                }
            }

            try
            {
               
                var dt = Helper.Get($"SELECT ID FROM Users WHERE Login=N'{LoginTextBox.Text}' AND Pass=N'{UserPasswordBox.Password}'");

                if (dt.Rows.Count > 0)
                {
                    Helper.RoleID = (int)dt.Rows[0][0];

                    MessageBox.Show("Авторизация прошла успешно!",
                                    "Информация", MessageBoxButton.OK, MessageBoxImage.Information);

                    MainWindow mainWindow = new MainWindow();
                    mainWindow.Show();
                    this.Close();
                }
                else
                {
                    HandleLoginFailure("Неверный логин или пароль.");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ошибка при подключении к базе данных: " + ex.Message,
                                "Критическая ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        // Метод обработки неудачной попытки входа
        private void HandleLoginFailure(string errorMessage)
        {
            _failedAttempts = _failedAttempts + 1;

            if (_failedAttempts >= 3)
            {
                MessageBox.Show("Система заблокирована из-за превышения попыток авторизации.",
                                "Блокировка", MessageBoxButton.OK, MessageBoxImage.Error);
                LoginButton.IsEnabled = false;
                return;
            }

            MessageBox.Show(errorMessage, "Ошибка входа", MessageBoxButton.OK, MessageBoxImage.Error);

            // Показываем капчу после первой ошибки
            if (CaptchaGroupBox.Visibility == Visibility.Collapsed)
            {
                CaptchaGroupBox.Visibility = Visibility.Visible;
            }

            MixPuzzleImages();
        }

        // Вращение картинки по клику мыши
        private void CaptchaImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Image clickedImage = sender as Image;

            // Достаем текущий угол поворота
            RotateTransform transform = clickedImage.RenderTransform as RotateTransform;

            if (transform == null)
            {
                transform = new RotateTransform(0);
                clickedImage.RenderTransform = transform;
            }

            // Поворачиваем на 90 градусов
            double currentAngle = transform.Angle;
            double nextAngle = currentAngle + 90;

            if (nextAngle >= 360)
            {
                nextAngle = 0;
            }

            transform.Angle = nextAngle;
        }

        // Метод для случайного перемешивания картинок
        private void MixPuzzleImages()
        {
            Random rnd = new Random();
            Image[] images = { CaptchaImage1, CaptchaImage2, CaptchaImage3, CaptchaImage4 };

            foreach (Image img in images)
            {
                // Генерируем случайный угол: 90, 180 или 270 (чтобы не было 0)
                int randomMultiplier = rnd.Next(1, 4);
                double randomAngle = randomMultiplier * 90;

                RotateTransform transform = new RotateTransform(randomAngle);
                img.RenderTransform = transform;
            }
        }

        // Метод проверки: все ли картинки стоят под углом 0 градусов
        private bool CheckPuzzleState()
        {
            Image[] images = { CaptchaImage1, CaptchaImage2, CaptchaImage3, CaptchaImage4 };

            foreach (Image img in images)
            {
                RotateTransform transform = img.RenderTransform as RotateTransform;

                // Если хоть одна картинка перевернута, возвращаем false
                if (transform == null || transform.Angle != 0)
                {
                    return false;
                }
            }
            return true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }
    }
}


edit

    <Grid>
        <StackPanel Margin="10">
            <TextBlock Text="Название:"/>
            <TextBox Name="TbTitle" Margin="0,0,0,5"/>
            <TextBlock Text="Цена:"/>
            <TextBox Name="TbCost" Margin="0,0,0,5"/>
            <TextBlock Text="Категория:"/>
            <ComboBox Name="CbType" DisplayMemberPath="Title" SelectedValuePath="ID" Margin="0,0,0,5"/>
            <CheckBox Name="CbAct" Content="Активен" IsChecked="True" Margin="0,10"/>
            <Button Content="Сохранить" Click="BtnSave_Click"/>
        </StackPanel>
    </Grid>

    int _id;
    public EditWindow(int id)
    {
        InitializeComponent();
        _id = id;
        CbType.ItemsSource = Helper.Get("SELECT * FROM Types").DefaultView;
        if (CbType.Items.Count > 0) CbType.SelectedIndex = 0;

        if (_id > 0)
        {
            var r = Helper.Get($"SELECT * FROM Items WHERE ID={_id}").Rows[0];
            TbTitle.Text = r["Title"].ToString();
            TbCost.Text = r["Cost"].ToString();
            CbType.SelectedValue = r["TypeID"];
            CbAct.IsChecked = (bool)r["IsActive"];
        }
    }

    private void BtnSave_Click(object sender, RoutedEventArgs e)
    {
        if (TbTitle.Text == "") return;
        string cost = TbCost.Text.Replace(",", "."); // Точка для SQL
        int typeId = (int)CbType.SelectedValue;
        bool act = CbAct.IsChecked == true;

        string sql = _id == 0
            ? $"INSERT INTO Items (Title, Cost, TypeID, IsActive) VALUES (N'{TbTitle.Text}', {cost}, {typeId}, '{act}')"
            : $"UPDATE Items SET Title=N'{TbTitle.Text}', Cost={cost}, TypeID={typeId}, IsActive='{act}' WHERE ID={_id}";

        try { Helper.Exec(sql); Close(); } catch { MessageBox.Show("Ошибка формата цены!"); }
    }
}


helper


namespace WpfApp // ЗАМЕНИ НА ИМЯ СВОЕГО ПРОЕКТА
{
    public static class Helper
    {
        // ВАЖНО: Вставь сюда свой сервер!
        public static string Cnn = @"Server=DESKTOP-HO3OQM8\SQLEXPRESS;Database=ExamDB;Trusted_Connection=True;";
        public static int RoleID = 0; // 1 - Админ, 2 - Юзер

        public static DataTable Get(string sql)
        {
            DataTable dt = new DataTable();
            try
            {
                using (SqlConnection c = new SqlConnection(Cnn))
                {
                    c.Open();
                    new SqlDataAdapter(sql, c).Fill(dt);
                }
            }
            catch { }
            return dt;
        }

        public static void Exec(string sql)
        {
            using (SqlConnection c = new SqlConnection(Cnn))
            {
                c.Open();
                new SqlCommand(sql, c).ExecuteNonQuery();
            }
        }
    }
}