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


Да. Ниже — полностью исправленный код под C# 7.3 без using var, без новых сокращённых конструкций, которые требуют более новой версии языка.

Я даю полные версии файлов, чтобы можно было просто заменить.

⸻

1. App.xaml

<Application x:Class="LabApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
    </Application.Resources>
</Application>


⸻

2. App.xaml.cs

using System.Windows;

namespace LabApp
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            LoginWindow window = new LoginWindow();
            window.Show();
        }
    }
}


⸻

3. LoginWindow.xaml

<Window x:Class="LabApp.LoginWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Авторизация" Height="280" Width="420" WindowStartupLocation="CenterScreen">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <TextBlock Text="Логин"/>
        <TextBox x:Name="tbLogin" Margin="0,25,0,10" Height="30"/>

        <TextBlock Grid.Row="1" Text="Пароль"/>
        <PasswordBox x:Name="pbPassword" Grid.Row="1" Margin="0,25,0,10" Height="30"/>

        <Button Grid.Row="2" Content="Войти" Height="35" Margin="0,10,0,0" Click="LoginClick"/>
        <TextBlock x:Name="tbMsg" Grid.Row="3" Margin="0,15,0,0" TextWrapping="Wrap"/>
    </Grid>
</Window>


⸻

4. LoginWindow.xaml.cs

using System;
using System.Data;
using System.Windows;
using MySqlConnector;

namespace LabApp
{
    public partial class LoginWindow : Window
    {
        private string cs = "Server=localhost;Port=3306;Database=lab_accounting_db;Uid=root;Pwd=12345;";

        public LoginWindow()
        {
            InitializeComponent();
        }

        private DataTable Q(string sql, params MySqlParameter[] p)
        {
            DataTable t = new DataTable();

            using (MySqlConnection c = new MySqlConnection(cs))
            {
                using (MySqlCommand m = new MySqlCommand(sql, c))
                {
                    if (p != null && p.Length > 0)
                    {
                        m.Parameters.AddRange(p);
                    }

                    using (MySqlDataAdapter a = new MySqlDataAdapter(m))
                    {
                        a.Fill(t);
                    }
                }
            }

            return t;
        }

        private void LoginClick(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(tbLogin.Text) || string.IsNullOrWhiteSpace(pbPassword.Password))
            {
                tbMsg.Text = "Введите логин и пароль";
                return;
            }

            try
            {
                DataTable t = Q(
                    @"select u.UserID, u.FullName, r.RoleName
                      from Users u
                      join Roles r on r.RoleID = u.RoleID
                      where u.Login = @l and u.PasswordHash = @p",
                    new MySqlParameter("@l", tbLogin.Text.Trim()),
                    new MySqlParameter("@p", pbPassword.Password.Trim())
                );

                if (t.Rows.Count == 0)
                {
                    tbMsg.Text = "Неверный логин или пароль";
                    return;
                }

                DataRow row = t.Rows[0];
                int userId = Convert.ToInt32(row["UserID"]);
                string fullName = Convert.ToString(row["FullName"]);
                string roleName = Convert.ToString(row["RoleName"]);

                MainWindow w = new MainWindow(userId, fullName, roleName);
                w.Show();
                Close();
            }
            catch (Exception ex)
            {
                tbMsg.Text = ex.Message;
            }
        }
    }
}


⸻

5. MainWindow.xaml

<Window x:Class="LabApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Учет лабораторных анализов" Height="700" Width="1200" WindowStartupLocation="CenterScreen">
    <Grid Margin="15">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Border BorderBrush="Gray" BorderThickness="1" Padding="10" Margin="0,0,0,10">
            <DockPanel>
                <StackPanel Orientation="Horizontal" DockPanel.Dock="Left">
                    <TextBlock Text="Пользователь: " FontWeight="Bold"/>
                    <TextBlock x:Name="tbUser" Margin="0,0,20,0"/>
                    <TextBlock Text="Роль: " FontWeight="Bold"/>
                    <TextBlock x:Name="tbRole"/>
                </StackPanel>

                <Button Content="Выйти" Width="100" Height="30" DockPanel.Dock="Right" Click="ExitClick"/>
            </DockPanel>
        </Border>

        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="3*"/>
                <ColumnDefinition Width="2*"/>
            </Grid.ColumnDefinitions>

            <TabControl Margin="0,0,10,0">
                <TabItem Header="Пациенты">
                    <DataGrid x:Name="dgPatients" IsReadOnly="True" CanUserAddRows="False"/>
                </TabItem>

                <TabItem Header="Исследования">
                    <DataGrid x:Name="dgTests" IsReadOnly="True" CanUserAddRows="False"/>
                </TabItem>
            </TabControl>

            <StackPanel Grid.Column="1">
                <TextBlock Text="Пациент"/>
                <ComboBox x:Name="cbPatients" Margin="0,5,0,10"/>

                <TextBlock Text="Тип анализа"/>
                <ComboBox x:Name="cbAnalysis" Margin="0,5,0,10"/>

                <TextBlock Text="Результат"/>
                <TextBox x:Name="tbResult" Height="30" Margin="0,5,0,10"/>

                <TextBlock Text="Комментарий"/>
                <TextBox x:Name="tbComment"
                         Height="100"
                         Margin="0,5,0,10"
                         AcceptsReturn="True"
                         TextWrapping="Wrap"/>

                <Button Content="Добавить исследование" Height="35" Margin="0,0,0,10" Click="AddTest"/>

                <TextBlock x:Name="tbMsg" TextWrapping="Wrap"/>
            </StackPanel>
        </Grid>
    </Grid>
</Window>


⸻

6. MainWindow.xaml.cs

using System;
using System.Data;
using System.Windows;
using MySqlConnector;

namespace LabApp
{
    public partial class MainWindow : Window
    {
        private string cs = "Server=localhost;Port=3306;Database=lab_accounting_db;Uid=root;Pwd=12345;";
        private int currentUserId;
        private string currentFullName;
        private string currentRoleName;

        public MainWindow(int userId, string fullName, string roleName)
        {
            InitializeComponent();

            currentUserId = userId;
            currentFullName = fullName;
            currentRoleName = roleName;

            tbUser.Text = currentFullName;
            tbRole.Text = currentRoleName;

            LoadData();
        }

        private DataTable Q(string sql, params MySqlParameter[] p)
        {
            DataTable t = new DataTable();

            using (MySqlConnection c = new MySqlConnection(cs))
            {
                using (MySqlCommand m = new MySqlCommand(sql, c))
                {
                    if (p != null && p.Length > 0)
                    {
                        m.Parameters.AddRange(p);
                    }

                    using (MySqlDataAdapter a = new MySqlDataAdapter(m))
                    {
                        a.Fill(t);
                    }
                }
            }

            return t;
        }

        private void X(string sql, params MySqlParameter[] p)
        {
            using (MySqlConnection c = new MySqlConnection(cs))
            {
                c.Open();

                using (MySqlCommand m = new MySqlCommand(sql, c))
                {
                    if (p != null && p.Length > 0)
                    {
                        m.Parameters.AddRange(p);
                    }

                    m.ExecuteNonQuery();
                }
            }
        }

        private void LoadData()
        {
            try
            {
                dgPatients.ItemsSource = Q(
                    @"select 
                        PatientID 'ID',
                        LastName 'Фамилия',
                        FirstName 'Имя',
                        MiddleName 'Отчество',
                        date_format(BirthDate, '%d.%m.%Y') 'Дата рождения',
                        Gender 'Пол',
                        Phone 'Телефон'
                      from Patients
                      order by LastName, FirstName, MiddleName"
                ).DefaultView;

                dgTests.ItemsSource = Q(
                    @"select
                        lt.LabTestID 'ID',
                        concat(p.LastName, ' ', p.FirstName, ' ', ifnull(p.MiddleName,'')) 'Пациент',
                        at.AnalysisName 'Анализ',
                        lt.ResultValue 'Результат',
                        at.Unit 'Ед.изм.',
                        at.ReferenceRange 'Норма',
                        date_format(lt.TestDate, '%d.%m.%Y %H:%i') 'Дата',
                        u.FullName 'Лаборант',
                        lt.CommentText 'Комментарий'
                      from LabTests lt
                      join Patients p on p.PatientID = lt.PatientID
                      join AnalysisTypes at on at.AnalysisTypeID = lt.AnalysisTypeID
                      join Users u on u.UserID = lt.UserID
                      order by lt.TestDate desc"
                ).DefaultView;

                cbPatients.ItemsSource = Q(
                    @"select
                        PatientID,
                        concat(LastName, ' ', FirstName, ' ', ifnull(MiddleName,''), ' [', date_format(BirthDate, '%d.%m.%Y'), ']') as FullInfo
                      from Patients
                      order by LastName, FirstName, MiddleName"
                ).DefaultView;

                cbAnalysis.ItemsSource = Q(
                    @"select
                        AnalysisTypeID,
                        concat(AnalysisName, ' (', Unit, ', норма: ', ReferenceRange, ')') as FullInfo
                      from AnalysisTypes
                      order by AnalysisName"
                ).DefaultView;

                cbPatients.DisplayMemberPath = "FullInfo";
                cbPatients.SelectedValuePath = "PatientID";

                cbAnalysis.DisplayMemberPath = "FullInfo";
                cbAnalysis.SelectedValuePath = "AnalysisTypeID";

                if (cbPatients.Items.Count > 0)
                {
                    cbPatients.SelectedIndex = 0;
                }

                if (cbAnalysis.Items.Count > 0)
                {
                    cbAnalysis.SelectedIndex = 0;
                }

                tbResult.Clear();
                tbComment.Clear();
                tbMsg.Text = "";
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void AddTest(object sender, RoutedEventArgs e)
        {
            decimal result;
            object commentValue;

            if (cbPatients.SelectedValue == null)
            {
                tbMsg.Text = "Выберите пациента";
                return;
            }

            if (cbAnalysis.SelectedValue == null)
            {
                tbMsg.Text = "Выберите анализ";
                return;
            }

            if (string.IsNullOrWhiteSpace(tbResult.Text))
            {
                tbMsg.Text = "Введите результат";
                return;
            }

            if (!decimal.TryParse(tbResult.Text.Trim().Replace('.', ','), out result))
            {
                tbMsg.Text = "Результат должен быть числом";
                return;
            }

            if (string.IsNullOrWhiteSpace(tbComment.Text))
            {
                commentValue = DBNull.Value;
            }
            else
            {
                commentValue = tbComment.Text.Trim();
            }

            try
            {
                X(
                    @"insert into LabTests
                      (PatientID, AnalysisTypeID, UserID, TestDate, ResultValue, CommentText)
                      values
                      (@p, @a, @u, now(), @r, @c)",
                    new MySqlParameter("@p", cbPatients.SelectedValue),
                    new MySqlParameter("@a", cbAnalysis.SelectedValue),
                    new MySqlParameter("@u", currentUserId),
                    new MySqlParameter("@r", result),
                    new MySqlParameter("@c", commentValue)
                );

                tbResult.Clear();
                tbComment.Clear();
                tbMsg.Text = "Данные успешно добавлены";

                dgTests.ItemsSource = Q(
                    @"select
                        lt.LabTestID 'ID',
                        concat(p.LastName, ' ', p.FirstName, ' ', ifnull(p.MiddleName,'')) 'Пациент',
                        at.AnalysisName 'Анализ',
                        lt.ResultValue 'Результат',
                        at.Unit 'Ед.изм.',
                        at.ReferenceRange 'Норма',
                        date_format(lt.TestDate, '%d.%m.%Y %H:%i') 'Дата',
                        u.FullName 'Лаборант',
                        lt.CommentText 'Комментарий'
                      from LabTests lt
                      join Patients p on p.PatientID = lt.PatientID
                      join AnalysisTypes at on at.AnalysisTypeID = lt.AnalysisTypeID
                      join Users u on u.UserID = lt.UserID
                      order by lt.TestDate desc"
                ).DefaultView;
            }
            catch (Exception ex)
            {
                tbMsg.Text = ex.Message;
            }
        }

        private void ExitClick(object sender, RoutedEventArgs e)
        {
            LoginWindow w = new LoginWindow();
            w.Show();
            Close();
        }
    }
}


⸻

7. Что именно я поменял под C# 7.3

Убрал конструкции, которые часто ломаются на старой версии:
	•	using var ...
	•	сокращённый new("@x", value)

Заменил на обычный стиль:

using (MySqlConnection c = new MySqlConnection(cs))
{
}

и

new MySqlParameter("@x", value)


⸻

8. Что не забудь поменять

Во всех .cs файлах укажи свой пароль:

private string cs = "Server=localhost;Port=3306;Database=lab_accounting_db;Uid=root;Pwd=12345;";


⸻

9. Если хочешь, я следующим сообщением так же полностью перепишу под C# 7.3 и сам SQL-скрипт с красивыми именами таблиц/полей для отчёта, либо сделаю сразу готовый вариант проекта с разграничением по ролям.