【问题标题】:MVP Winforms and textbox combobox valuesMVP Winforms 和文本框组合框值
【发布时间】:2023-03-07 14:45:01
【问题描述】:

我有一个带有列表作为数据源的组合框。此列表包含对象(客户)及其属性(名称、地址、...)。 当我选择组合框的一个项目时,我想将信息(地址、邮政编码...)传递给表单上的某些文本框。 在我的测试 1tier 应用程序中,这是正确的。 但是我正在开发的主要应用程序是基于 MVP 的(我自己对此有所了解)。我面临的问题是选角。由于我的观点不知道我的模型,我不应该被允许使用(客户)。 string address = ((Customers)comboBox1.SelectedItem).CustomerAddress;

1Tier 测试代码:

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();
    }
}

【问题讨论】:

    标签: c# winforms combobox mvp


    【解决方案1】:

    这只是实现它的一种方式。您的 MVP 模式可能看起来不同。 在这个实现中,View 知道 Presenter。有关 MVP 的更多信息,您可以查看here

    您可以将 Presenter 用作客户的包装器:

    public interface IPresenter
    {
        void Init();
        void SetSelectedCustomer(int customerId);
        IEnumerable GetCustomers();
        string FirstName { get; set; }
        string LastName { get; set; }
        string Address { get; set; }
    }
    

    Presenter 必须实现 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)));
        }
    }
    

    您可以在组合框中的 SelectedIndexChanged 事件中的 Presenter 处设置选定的 CustomerId:

    _presenter.SetSelectedCustomer((int)comboBox1.SelectedValue);
    

    Presenter 中的 SetSelectedCustomer 方法(或 SelectedCustomerChanged 事件的 EventHandler)选择具有给定 CustomerId 的客户并设置 FirstName、LastName 和 Address:

    public void SetSelectedCustomer(int customerId)
    {
        var customer = _repository.GetCustomerById(customerId);
        FirstName = customer.FirstName;
        LastName = customer.LastName;
        Address = customer.Address;
    }
    

    您应该在 Form_Load 中为 TextBoxes 进行绑定:

    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)));
    

    【讨论】:

      【解决方案2】:

      如果您绝对反对允许您的视图访问您的域对象——那些代表数据表行的对象(根据它们的重量,在某些情况下可能没问题)——你可能想研究一下使用 DTO。检查this 以获得对注意事项的良好描述和一种方法。注意底部提到的Automapper。这是一个很棒的工具。

      编辑:我刚刚意识到您对 Winforms 解决方案感兴趣,而不是针对 ASP.NET 的解决方案。虽然上面的链接涉及 ASP.NET,但 Winforms 应用程序的想法是相同的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-15
        • 2011-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多