MVP Winforms и текстовые поля со списком значений
У меня есть поле со списком в качестве источника данных. Этот список содержит объекты (клиенты) с их свойствами (имя, адрес, ...). Когда я выбираю элемент в выпадающем списке, я хочу передать информацию (адрес, почтовый индекс...) в некоторые текстовые поля в моей форме. В моем тесте 1tier приложения это работает правильно. Но основное приложение, над которым я работаю, основано на MVP (с моим собственным прикосновением к нему). Проблема, с которой я сталкиваюсь - это кастинг. Поскольку мое мнение не знает мою модель, мне нельзя разрешать использовать (Клиенты). string address = ((Customers)comboBox1.SelectedItem).CustomerAddress;
1 Уровень тестирования кода:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
//getCustomers((int)comboBox1.SelectedValue);
//txtAddress.Text =Convert.ToString( comboBox1.SelectedValue);
Customers p = (Customers)comboBox1.SelectedItem;
string s = comboBox1.SelectedItem.ToString();
string address = ((Customers)comboBox1.SelectedItem).CustomerAddress;
txtAddress1.Text = address;
}
private void Form3_Load(object sender, EventArgs e)
{
using (var emp = new EmployerEFEntities())
{
var query = from customers in emp.Customers
select customers;
comboBox1.DisplayMember = "CustomerName";
comboBox1.ValueMember = "CustomerID";
comboBox1.DataSource = query.ToList();
}
}
Я искал это в течение нескольких дней, но не достиг успеха. Я надеюсь, что кто-то может дать мне правильное направление.
Код реального приложения:
Посмотреть:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
txtName.Text = comboBox1.SelectedValue.ToString();
}
private void CustomerView_Load(object sender, EventArgs e)
{
comboBox1.DataSource = customerPresenter.getCustomers();
comboBox1.DisplayMember = "CustomerName";
comboBox1.ValueMember = "CustomerId";
}
Ведущий:
public List<tbl_customer> getCustomers()
{
using (var customers = new DBCrownfishEntities())
{
var customer = from c in customers.tbl_customer
select c;
return customer.ToList();
}
}
2 ответа
Это всего лишь один из способов его реализации. Ваш шаблон MVP может выглядеть иначе. В этой реализации View знает Presenter. Для получения дополнительной информации о MVP вы можете посмотреть здесь
Вы можете использовать Presenter в качестве оболочки для вашего клиента:
public interface IPresenter
{
void Init();
void SetSelectedCustomer(int customerId);
IEnumerable GetCustomers();
string FirstName { get; set; }
string LastName { get; set; }
string Address { get; set; }
}
Презентатор должен реализовать INotifyPropertyChanged (и вызвать OnPropertyChanged в установщиках свойств).
public class Presenter : IPresenter, INotifyPropertyChanged
{
private readonly Repository _repository;
private string _firstName;
private string _lastName;
private string _address;
private Customer _currentCustomer;
public Presenter(Repository repository)
{
_repository = repository;
}
public string FirstName
{
get { return _firstName; }
set
{
if (_firstName == value) return;
_firstName = value;
OnPropertyChanged();
}
}
public string LastName
{
get { return _lastName; }
set
{
if (_lastName == value) return;
_lastName = value;
OnPropertyChanged();
}
}
public string Address
{
get { return _address; }
set
{
if (_address == value) return;
_address = value;
OnPropertyChanged();
}
}
public IEnumerable GetCustomers()
{
return _repository.GetAllCustomers();
}
public void Init()
{
var result = _repository.GetAllCustomers();
SetSelectedCustomer(result[0].Id);
}
public void SetSelectedCustomer(int customerId)
{
var customer = _repository.GetCustomerById(customerId);
FirstName = customer.FirstName;
LastName = customer.LastName;
Address = customer.Address;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Вот как выглядит вид:
public partial class Form1 : Form
{
private IPresenter _presenter;
private bool _initialized;
public Form1(IPresenter presenter)
{
InitializeComponent();
_presenter = presenter;
_presenter.Init();
SetComboBoxData(_presenter.GetCustomers());
_initialized = true;
}
public void SetComboBoxData(IEnumerable data)
{
comboBox1.DataSource = data;
comboBox1.ValueMember = "Id";
comboBox1.DisplayMember = "FirstName";
}
private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
if (!_initialized) return;
_presenter.SetSelectedCustomer((int)comboBox1.SelectedValue);
}
private void Form1_Load(object sender, System.EventArgs e)
{
textBox1.DataBindings.Add(new Binding("Text", _presenter, nameof(_presenter.FirstName)));
textBox2.DataBindings.Add(new Binding("Text", _presenter, nameof(_presenter.LastName)));
textBox3.DataBindings.Add(new Binding("Text", _presenter, nameof(_presenter.Address)));
}
}
Вы можете установить выбранный CustomerId в Presenter в своем событии SelectedIndexChanged из вашего выпадающего списка:
_presenter.SetSelectedCustomer((int)comboBox1.SelectedValue);
Метод SetSelectedCustomer в Presenter (или EventHandler для события SelectedCustomerChanged) выбирает Customer с заданным CustomerId и устанавливает FirstName, LastName и Address:
public void SetSelectedCustomer(int customerId)
{
var customer = _repository.GetCustomerById(customerId);
FirstName = customer.FirstName;
LastName = customer.LastName;
Address = customer.Address;
}
Вы должны сделать привязку для TextBoxes в Form_Load:
textBox1.DataBindings.Add(new Binding("Text", _presenter, nameof(_presenter.FirstName)));
textBox2.DataBindings.Add(new Binding("Text", _presenter, nameof(_presenter.LastName)));
textBox3.DataBindings.Add(new Binding("Text", _presenter, nameof(_presenter.Address)));
Если вы категорически против предоставления вашему представлению доступа к вашим доменным объектам - тем, которые представляют строки таблицы данных (что, в зависимости от того, насколько они тяжелы, в некоторых ситуациях может быть приемлемым)- вы можете захотеть использовать DTO. Проверьте это для хорошего описания соображений и одного подхода к этому. Обратите внимание на упоминание Automapper внизу. Это отличный инструмент.
РЕДАКТИРОВАТЬ: Я только что понял, что вы заинтересованы в решении Winforms, а не для ASP.NET. Хотя приведенная выше ссылка касается ASP.NET, идея аналогична для приложений Winforms.