не смог найти тему с ответом на мой вопрос. Есть база данных на локальном сервере MySql. Создаю приложение Windows Forms, соединение устанавливается с БД, но данные не выводятся в DataGridView. Точнее выводятся, но пишет System.Collections.Generic.List`1[System.String] за место данных и то только в 1-ом столбце. Не могу понять что это. Подскажите пожалуйста как мне сделать работоспособную программу
Вот код соединения с БД. Метод public List[] Select() создаёт список для вывода.
class DBconnect
{
private MySqlConnection connection;
private string server, database, uid, password;
public DBconnect()
{
Initialize();
}
private void Initialize()
{
server = "localhost";
database = "catalog_personal";
uid = "root";
password = " ";
string connectionString;
connectionString = " SERVER =" + server + " ;" + " DATABASE =" +
database + " ;" + " UID =" + uid + " ;" + "PASSWORD =" + password + " ;";
connection = new MySqlConnection(connectionString);
}
//Открываем соединение
private bool OpenConnection()
{
try
{
connection.Open();
return true;
}
catch(MySqlException ex)
{
// При обработке ошибок вы можете основывать ответ вашего приложения
// по номеру ошибки.
// Два наиболее распространенных номера ошибок при подключении:
// 0: не удается подключиться к серверу.
// 1045: неверное имя пользователя и / или пароль.
switch(ex.Number)
{
case 0:
MessageBox.Show("Невозможно подключиться к серверу, " +
"связаться с админ-панелью");
break;
case 1045:
MessageBox.Show("Неверное имя пользователя / пароль, " +
"пожалуйста, попробуйте еще раз");
break;
}
return false;
}
}
//Закрываем соединение
private bool CloseConnection()
{
try
{
connection.Close();
return true;
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
public List<string>[] Select()
{
string query = " SELECT * FROM personal";
//Создаем список для сохранения результа вывода
List<string>[] list = new List<string>[4];
list[0] = new List<string>();
list[1] = new List<string>();
list[2] = new List<string>();
list[3] = new List<string>();
//Открываем соединение
if (this.OpenConnection() == true)
{
//Создаем команду
MySqlCommand cmd = new MySqlCommand(query, connection);
//Создаем читатель данных и выполняем команду чтения
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
list[0].Add(dataReader[0].ToString());
list[1].Add(dataReader[1].ToString());
list[2].Add(dataReader[2].ToString());
list[3].Add(dataReader[3].ToString());
}
this.CloseConnection();
return list;
}
else
{
return list;
}
}
}
Код в Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
LoadData();
}
private void LoadData()
{
DBconnect db = new DBconnect();
foreach (var s in db.Select())
{
dataGridView1.Rows.Add(s);
}
}
}
Вот что получается в результате, прикрепляю скрин
Рассмотрим подробнее ваш пример. Вот вы "набросали" на форму контролы, и вам нужно начать программировать работу с ними. Что бы тут хотелось бы...
Во-первых, не торопитесь сразу создавать БД и подключаться к ней. Для быстрого прототипирования приложения БД не нужна и даже вредна, т.к. отвлекает время и внимание на работу с ней.
Во-вторых, в прил. необходимо выделить слои, минимально 3: слой отображения (визуальный интерфейс), слой модели предметной области с кот. работает ваше прил. и слой хранения (это как раз работа с БД).
Начнем с создания модели. У нас модель достаточно простая. Я добавил еще статич. метод для клонирования экземпляра класса, зачем? Объясню ниже.
public class Employee
{
public int Id { get; set; }
//порядковый номер для отображения в DGV
public int OrderNumber { get; set; }
//имя
public string FirstName { get; set; }
//фамилия
public string LastName { get; set; }
public string Phone { get; set; }
public Employee(int id, string firstName = "<?>", string lastName = "<?>", string phone = "<?>")
{
Id = id;
FirstName = firstName;
LastName = lastName;
Phone = phone;
}
/// <summary>
/// Получение клонированного экземпляра
/// </summary>
/// <param name="employee">существующий экземпляр</param>
/// <returns>клон существующего сотрудника</returns>
public static Employee GetClone(Employee employee)
{
if (employee is null)
throw new System.ArgumentNullException(nameof(employee));
return new Employee(employee.Id)
{
FirstName = employee.FirstName,
LastName = employee.LastName,
Phone = employee.Phone,
};
}
public override string ToString()
{
return $"{Id}: {FirstName} {LastName}";
}
}
Слой хранения начнем с абстракции, с создания интерфейса репозитория.
public interface IEmployeeRepository
{
//получение всех
Task<Result<List<Employee>>> GetEmployees();
//добавление
Task<Result<int>> AddEmployee(Employee employee);
//удаление
Task<Result<int>> RemoveEmployee(int id);
//обновление
Task<Result<int>> UpdateEmployee(Employee emp);
}
Здесь мы объявляем все нужные нам для работы методы. Кстати, вы можете начинать прямо с пустого интерфейса, и по мере надобности добавлять в него нужные члены. Обратите внимание, что предполагается работа в асинхронном режиме, и да, есть еще какой-то Result<T>
!
Result<T>
- это пример т.н. монады, спец. класса для возвращения результата в случае если в методе возникнет ошибка или результат может быть равным null
. Подробнее см.видео. Вот его код
/// <summary>
/// Монада Result для возвращения результата вместо null
/// и для случаев когда возникает Exception, а результат из метода
/// нужно возвращать какой-то
/// </summary>
/// <typeparam name="T"></typeparam>
public class Result<T>
{
public readonly T Value;
public readonly string Error;
//ctors
public Result(T value)
{
Value = value;
Error = String.Empty;
}
public Result(string error)
{
Error = error;
}
public bool HasValue => String.IsNullOrEmpty(Error);
public static implicit operator bool(Result<T> result)
{
return result.HasValue;
}
}
Теперь вернемся к интерфейсу приложения. Код формы такой
public partial class MainForm : Form
{
//Источник данных для DGV
private BindingSource _bsEmployees;
//редактируемый сотрудник
private BindingSource _bsCurrentEmployee;
//работа с БД
private IEmployeeRepository _repo;
public MainForm()
{
InitializeComponent();
StartPosition = FormStartPosition.CenterScreen;
Text = "Пример работы с MySql";
//установка привязок
SetBindings();
this.Load += MainForm_Load;
}
private void MainForm_Load(object sender, EventArgs e)
{
//тестовый репозиторий
_repo = new TestRepository();
//Загрузка данных
LoadData();
//кнопки
_buttonAdd.Click += ButtonAdd_Click;
_buttonRemove.Click += ButtonRemove_Click;
_buttonSave.Click += ButtonSave_Click;
_buttonNext.Click += ButtonNext_Click;
_buttonPrev.Click += ButtonPrev_Click;
//клик по строке в DGV
_dataGridViewEmployees.MouseClick += (s, a) => SetCurrentEmployee();
}
private void SetBindings()
{
_bsEmployees = new BindingSource();
_bsEmployees.DataSource = typeof(List<Employee>);
//привязки для DGV
_dataGridViewEmployees.AutoGenerateColumns = false;
_dataGridViewEmployees.DataSource = _bsEmployees;
//привязки у столбцов
_columnNumber.DataPropertyName = nameof(Employee.OrderNumber);
_columnFirstName.DataPropertyName = nameof(Employee.FirstName);
_columnLastName.DataPropertyName = nameof(Employee.LastName);
_columnPhone.DataPropertyName = nameof(Employee.Phone);
//текстбоксы
_bsCurrentEmployee = new BindingSource();
_bsCurrentEmployee.DataSource = new List<Employee> { new Employee(0) };
_textBoxFirstName.DataBindings.Add("Text", _bsCurrentEmployee, nameof(Employee.FirstName));
_textBoxLastName.DataBindings.Add("Text", _bsCurrentEmployee, nameof(Employee.LastName));
_textBoxPhone.DataBindings.Add("Text", _bsCurrentEmployee, nameof(Employee.Phone));
}
private async void LoadData()
{
//получаем
var result = await _repo.GetEmployees();
if (result)
{
//извлекаем
List<Employee> employees = result.Value;
//пронумеровываем
int i = 1;
employees.ForEach(e => e.OrderNumber = i++);
//отображаем
_bsEmployees.DataSource = employees;
_bsEmployees.MoveFirst();
SetCurrentEmployee();
}
else
{
MessageBox.Show(result.Error, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
//курсор на последнего
_bsEmployees.MoveLast();
//след.порядковый номер
int number = (_bsEmployees.Current as Employee).OrderNumber + 1;
//добавляем нового
_bsEmployees.Add(new Employee(0) { OrderNumber = number });
//выделяем его
_bsEmployees.MoveNext();
SetCurrentEmployee();
//выделяем имя для редактирования
_textBoxFirstName.Focus();
}
private async void ButtonSave_Click(object sender, EventArgs e)
{
SwitchOnWaiting();
var current = (Employee)_bsCurrentEmployee.Current;
Result<int> result;
try
{
if (current.Id == 0)
{
//добавляем нового сотрудника
result = await _repo.AddEmployee(current);
}
else
{
//иначе обновляем существующего сотрудника
result = await _repo.UpdateEmployee(current);
}
if (result)
{
//перечитываем данные
LoadData();
}
}
finally
{
SwitchOffWaiting();
}
if(!result)
{
MessageBox.Show(result.Error, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private async void ButtonRemove_Click(object sender, EventArgs e)
{
SwitchOnWaiting();
//получаем текущего
var employee = (Employee)_bsEmployees.Current;
Result<int> result;
try
{
//удаляем из БД
result = await _repo.RemoveEmployee(employee.Id);
if (result)
{
//удаляем из отображения
_bsEmployees.Remove(employee);
_bsEmployees.MoveFirst();
SetCurrentEmployee();
}
}
finally
{
SwitchOffWaiting();
}
if (!result)
{
MessageBox.Show(result.Error, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonPrev_Click(object sender, EventArgs e)
{
_bsEmployees.MovePrevious();
SetCurrentEmployee();
}
private void ButtonNext_Click(object sender, EventArgs e)
{
_bsEmployees.MoveNext();
SetCurrentEmployee();
}
private void SetCurrentEmployee()
{
if (_bsEmployees.Count > 0)
{
_bsCurrentEmployee.List[0] = Employee.GetClone((Employee)_bsEmployees.Current);
}
else
{
_bsCurrentEmployee.List[0] = new Employee(0);
}
_bsCurrentEmployee.ResetItem(0);
}
private void SwitchOnWaiting()
{
foreach (var button in this.Controls.OfType<Button>())
{
button.Enabled = false;
}
_dataGridViewEmployees.Enabled = false;
Cursor = Cursors.WaitCursor;
}
private void SwitchOffWaiting()
{
foreach (var button in this.Controls.OfType<Button>())
{
button.Enabled = true;
}
_dataGridViewEmployees.Enabled = true;
Cursor = Cursors.Default;
}
}
На что хотелось бы обратить внимание.
Работаем через привязки, используем для этого два экземпляра BindingSource
, один для DataGridView
, второй для текстбоксов текущего редактируемого или создаваемого нового сотрудника. По клику на DGV
или переходе с пом.кнопок к следующему или предыдущему создается клон и привязывается текстбоксам. Сделано так для того, чтобы исключить одновременное изменение свойств выделенного сотрудника в DGV
и пользователь понимал, что необходимо нажать кнопку Сохранить
для запоминания изменений.
В методе MainForm_Load()
сделано подключение к фейковой БД _repo = new TestRepository();
или точнее классу реализующему IEmployeeRepository
c тестовыми данными. Рассмотрим его
class TestRepository : IEmployeeRepository
{
private List<Employee> _employees;
public TestRepository()
{
_employees = new List<Employee>
{
new Employee(1, "Иван", "Голунов", "+7561234567"),
new Employee(2, "Сергей", "Смирнов", "+77861234567"),
new Employee(3, "Дарья", "Смирнова", "+798475563"),
new Employee(4, "Кристина", "Семяжко", "+7304985023"),
new Employee(5, "Владимир", "Драгунов", "+73431234567"),
};
}
public Task<Result<List<Employee>>> GetEmployees()
{
var result = new List<Employee>();
foreach (var e in _employees)
{
var emp = new Employee(e.Id, e.FirstName, e.LastName, e.Phone);
result.Add(emp);
}
return Task.FromResult(new Result<List<Employee>>(result));
}
public Task<Result<int>> AddEmployee(Employee employee)
{
if (employee is null)
throw new ArgumentNullException(nameof(employee));
if (String.IsNullOrWhiteSpace(employee.FirstName)
|| String.IsNullOrEmpty(employee.FirstName))
{
return Task.FromResult(new Result<int>("Введите имя сотрудника."));
}
if (String.IsNullOrWhiteSpace(employee.LastName)
|| String.IsNullOrEmpty(employee.LastName))
{
return Task.FromResult(new Result<int>("Введите фамилию сотрудника."));
}
if (employee is null || employee.Id > 0)
throw new ArgumentNullException(nameof(employee));
if (_employees.Count > 0)
{
employee.Id = _employees.Max(e => e.Id) + 1;
}
else
{
employee.Id = 1;
}
_employees.Add(employee);
return Task.FromResult(new Result<int>(1));
}
public Task<Result<int>> RemoveEmployee(int id)
{
if (id <= 0)
throw new ArgumentException(nameof(id));
var emp = _employees.FirstOrDefault(e => e.Id == id);
if (emp != null)
{
_employees.Remove(emp);
}
return Task.FromResult(new Result<int>(1));
}
public Task<Result<int>> UpdateEmployee(Employee employee)
{
if (employee is null)
throw new ArgumentNullException(nameof(employee));
if (String.IsNullOrWhiteSpace(employee.FirstName)
|| String.IsNullOrEmpty(employee.FirstName))
{
return Task.FromResult(new Result<int>("Введите имя сотрудника."));
}
if (String.IsNullOrWhiteSpace(employee.LastName)
|| String.IsNullOrEmpty(employee.LastName))
{
return Task.FromResult(new Result<int>("Введите фамилию сотрудника."));
}
var emp = _employees.FirstOrDefault(e => e.Id == employee.Id);
if (emp != null)
{
emp.FirstName = employee.FirstName;
emp.LastName = employee.LastName;
emp.Phone = employee.Phone;
}
return Task.FromResult(new Result<int>(1));
}
}
Представьте на минутку, вы фрилансер и у вас заказ на подобную программу. Вам нужно быстро разработать прототип и предоставить заказчику, чтоб он мог этот прототип запустить и посмотреть, оценить и проч. Если бы вы использовали сразу подключение к реальной БД у вас бы возникли трудности, не правда ли... А так без проблем, компилируем и отправляем экзешник по почте.
Заказчик доволен? :) Пишем работу с реальной БД.
class MySqlRepository : IEmployeeRepository
{
public MySqlRepository()
{ }
private MySqlConnection GetConnection()
{
var cs = ConfigurationManager.ConnectionStrings["MySqlConn"].ToString();
var builder = new MySqlConnectionStringBuilder(cs);
//чтоб избежать проблем с русским языком
builder.CharacterSet = "utf8";
return new MySqlConnection(builder.ConnectionString);
}
public async Task<Result<List<Employee>>> GetEmployees()
{
var list = new List<Employee>();
try
{
using (var con = GetConnection())
using (var cmd = con.CreateCommand())
{
cmd.CommandText = "SELECT * FROM employees";
con.Open();
using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
var emp = new Employee(reader.GetInt32(0));
emp.FirstName = reader.GetString(1);
emp.LastName = reader.GetString(2);
emp.Phone = reader.GetString(3);
list.Add(emp);
}
}
}
}
catch (MySqlException ex)
{
return new Result<List<Employee>>(GetUserFriendlyErrorMessage(ex));
}
catch (Exception ex)
{
return new Result<List<Employee>>(ex.Message);
}
return new Result<List<Employee>>(list);
}
public async Task<Result<int>> AddEmployee(Employee employee)
{
if (employee is null)
throw new ArgumentNullException(nameof(employee));
if (String.IsNullOrWhiteSpace(employee.FirstName)
|| String.IsNullOrEmpty(employee.FirstName))
{
return new Result<int>("Введите имя сотрудника.");
}
if (String.IsNullOrWhiteSpace(employee.LastName)
|| String.IsNullOrEmpty(employee.LastName))
{
return new Result<int>("Введите фамилию сотрудника.");
}
int result = 0;
try
{
using (var con = GetConnection())
using (var cmd = con.CreateCommand())
{
cmd.CommandText = "INSERT INTO employees (first_name, last_name, phone)" +
" VALUES(@firstName, @lastName, @phone)";
cmd.Parameters.Add(new MySqlParameter("@firstName", MySqlDbType.VarChar, 200)
{ Value = employee.FirstName });
cmd.Parameters.Add(new MySqlParameter("@lastName", MySqlDbType.VarChar, 300)
{ Value = employee.LastName });
cmd.Parameters.Add(new MySqlParameter("@phone", MySqlDbType.VarChar, 45)
{
Value = employee.Phone ?? (object)System.DBNull.Value
});
con.Open();
result = await cmd.ExecuteNonQueryAsync();
}
}
catch (MySqlException ex)
{
return new Result<int>(GetUserFriendlyErrorMessage(ex));
}
catch (Exception ex)
{
return new Result<int>(ex.Message);
}
return new Result<int>(result);
}
public async Task<Result<int>> RemoveEmployee(int id)
{
if (id <= 0)
throw new ArgumentException(nameof(id));
int result = 0;
try
{
using (var con = GetConnection())
using (var cmd = con.CreateCommand())
{
cmd.CommandText = "DELETE FROM employees WHERE id =@id";
cmd.Parameters.Add(new MySqlParameter("@id", MySqlDbType.Int32)
{ Value = id });
con.Open();
result = await cmd.ExecuteNonQueryAsync();
}
}
catch (MySqlException ex)
{
return new Result<int>(GetUserFriendlyErrorMessage(ex));
}
catch (Exception ex)
{
return new Result<int>(ex.Message);
}
return new Result<int>(result);
}
public async Task<Result<int>> UpdateEmployee(Employee employee)
{
if (employee is null)
throw new ArgumentNullException(nameof(employee));
if (String.IsNullOrWhiteSpace(employee.FirstName)
|| String.IsNullOrEmpty(employee.FirstName))
{
return new Result<int>("Введите имя сотрудника.");
}
if (String.IsNullOrWhiteSpace(employee.LastName)
|| String.IsNullOrEmpty(employee.LastName))
{
return new Result<int>("Введите фамилию сотрудника.");
}
int result = 0;
try
{
using (var con = GetConnection())
using (var cmd = con.CreateCommand())
{
cmd.CommandText = "UPDATE employees" +
" SET first_name = @firstName, last_name = @lastName, phone = @phone" +
" WHERE id =@id";
cmd.Parameters.Add(new MySqlParameter("@firstName", MySqlDbType.VarChar, 200)
{ Value = employee.FirstName });
cmd.Parameters.Add(new MySqlParameter("@lastName", MySqlDbType.VarChar, 300)
{ Value = employee.LastName });
cmd.Parameters.Add(new MySqlParameter("@phone", MySqlDbType.VarChar, 45)
{
Value = employee.Phone ?? (object)System.DBNull.Value
});
cmd.Parameters.Add(new MySqlParameter("@id", MySqlDbType.Int32)
{ Value = employee.Id });
con.Open();
result = await cmd.ExecuteNonQueryAsync();
}
}
catch (MySqlException ex)
{
return new Result<int>(GetUserFriendlyErrorMessage(ex));
}
catch (Exception ex)
{
return new Result<int>(ex.Message);
}
return new Result<int>(result);
}
private string GetUserFriendlyErrorMessage(MySqlException ex)
{
var message = String.Empty;
switch (ex.Number)
{
case 0:
if (ex.InnerException.Message.Contains("Unknown"))
{
message = "Неверное название схемы или таблицы.";
}
else if (ex.InnerException.Message.Contains("Access"))
{
message = "Неверное имя или пароль доступа.";
}
else
{
message = ex.Message;
}
break;
case 1042:
message = "Сервер по указанному адресу не доступен." +
"\nОшибка ожидания.";
break;
case 1045:
message = "Неверное имя пользователя или пароль, " +
"\nпожалуйста, попробуйте еще раз.";
break;
default:
message = ex.Message;
break;
}
return message;
}
}
В методе GetConnection()
параметры соединения читаются из файла App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<connectionStrings>
<add name="MySqlConn"
providerName="MySql.Data.MySqlClient"
connectionString="Server=192.168.0.250;Port=3306;Database=EmployeesDb;Uid=admin;
Pwd=Mysql17;"/>
</connectionStrings>
</configuration>
Для работы с этим классом, нужно вернуться в код формы и в методе MainForm_Load()
изменить строчку получения экземпляра репозитория _repo = new MySqlRepository();
.
Да, и не забудьте сначала получить деньги от заказчика :)
Пример лежит здесь.
Для конструирования строки соединения можно использовать специальный класс-билдер.
При установлении соединения вы оставили только два случая в switch/case, а остальные отбрасываются. В итоге пользователь не получит никакого сообщения, если что-то пойдёт не так. Нужно, например, добавить дополнительную ветку default.
Современная разработка подразумевает использования моделей данных. Свойства класса-модели должны соответствовать колонкам в таблице базы данных. Я не знаю, какие у вас колонки, но, судя по форме, это Имя, Фамилия, Телефон. Поэтому, класс-модель будет такой:
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
}
Добавьте необходимые свойства с нужными типами (например, Id типа int и т. п.)
При чтении данных из БД создаём экземпляры нашего класса-модели, заполняем его свойства и добавляем в список.
class DBconnect
{
private readonly MySqlConnection connection;
public DBconnect()
{
var builder = new MySqlConnectionStringBuilder();
builder.Server = "localhost";
builder.Database = "catalog_personal";
builder.UserID = "root";
//builder.Password = "";
connection = new MySqlConnection(builder.ConnectionString);
}
private bool OpenConnection()
{
try
{
connection.Open();
return true;
}
catch (MySqlException ex)
{
switch (ex.Number)
{
case 0:
MessageBox.Show("Невозможно подключиться к серверу, " +
"связаться с админ-панелью");
break;
case 1045:
MessageBox.Show("Неверное имя пользователя / пароль, " +
"пожалуйста, попробуйте еще раз");
break;
default:
MessageBox.Show(ex.Message);
break;
}
return false;
}
}
private void CloseConnection()
{
try
{
connection.Close();
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
}
}
public List<Person> Select()
{
string query = " SELECT * FROM personal";
var list = new List<Person>();
if (OpenConnection())
{
using (var cmd = new MySqlCommand(query, connection))
using (var dataReader = cmd.ExecuteReader())
{
while (dataReader.Read())
{
var person = new Person();
person.FirstName = dataReader.GetString(0);
person.LastName = dataReader.GetString(1);
person.Phone = dataReader.GetString(2);
list.Add(person);
}
}
CloseConnection();
}
return list;
}
}
Также используем привязку данных (binding) вместо ручного добавления.
private void LoadData()
{
var db = new DBconnect();
dataGridView1.DataSource = db.Select();
}
Переписал ваш код через MySqlDataAdapter, он очень сильно сократился.
Как упражнение, можете переписать его через модели (будет чуть побольше и посложнее, но правильнее и гибчее).
class DBconnect
{
private MySqlConnection connection;
private string server, database, uid, password;
public DBconnect()
{
Initialize();
}
private void Initialize()
{
...
}
//Открываем соединение
private bool OpenConnection()
{
...
}
//Закрываем соединение
private bool CloseConnection()
{
...
}
public DataTable Select()
{
var dt = new DataTable();
if (this.OpenConnection() == true)
{
MySqlDataAdapter da = new MySqlDataAdapter();
da.SelectCommand.Connection = this.connection;
da.SelectCommand.CommandText = " SELECT * FROM personal";
da.Fill(dt);
this.CloseConnection();
}
return dt;
}
}
Код в Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
LoadData();
}
private void LoadData()
{
DBconnect db = new DBconnect();
dataGridView1.DataSource = db.Select();
}
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Никак не могу решить проблему с конверсиейВ БД значение столбцов : date и time, использую DateTimePicker в WinForms и создаю новые переменные в которые записываю...
Есть файлы расширения cs, которые генерируются утилитойМне необходимо программно проверять на корректность сгенерируемые файлы программно
В общем, есть много Word'ов, которые я обрабатываю через interop и пытаюсь вытянуть картинки, что бы их сохранить отдельно
Подскажите как в Xaml, через DataContext или ItemSource(или я не правильно думаю, что бы прибиндить из XAML свою коллекцию _ListProduct(Желательно с тремя столбиками,...