Использование BindingSource в UserControl

У меня есть UserControl с несколькими полями, которые я хотел бы привязать к BindingSource. Я также хотел бы, чтобы UserControl предоставлял некоторое свойство BindingSource, чтобы его можно было отбрасывать в форме и связывать с BindingSource в форме. Есть простой способ сделать это? Я понимаю, что могу перепривязать все элементы управления UserControl в его установщике BindSource. Но это кажется неправильным. Есть ли прокси BindingSource, который позволит мне связать BindingSource в пользовательском элементе управления с BindingSource в форме?

 Will Marcouiller15 июн. 2010 г., 20:49
Возможно, вы могли бы принять ответ, который другие дают на ваш вопрос. Я думаю, что это был бы хороший способ поблагодарить тех, кто нашел время, чтобы ответить и помочь вам, независимо от того, помогли они или нет, они потратили это время для вас.
 Larry20 нояб. 2015 г., 14:35
В Visual Basic Power Pack есть DataRepeater, который отлично работает и справляется с утомительной работой по созданию / удалению / привязке элементов управления сведений.msdn.microsoft.com/en-us/library/cc425010(v=vs.80).aspx
 Will Marcouiller22 сент. 2009 г., 03:58
Возможно, вы могли бы открыть свойство объекта BindingSource.DataSource, написав свойство, которое вы бы назвали DataSource, и это установит свойство BindingSource.DataSource вашей формы. В противном случае, пожалуйста, попробуйте объяснить, что вы хотите сделать, или привести конкретный пример, который поможет нам лучше понять. Когда я читаю, в моей голове все еще немного размыто. Вы хотите установить источник данных во время разработки? Хотите открыть свойства BindingSource в окне свойств? Хотите ли вы привязать элементы управления UserControl к конкретному элементу DataMember из изменений в дизайне BindingSource? N?
 profimedica28 июл. 2012 г., 08:42
Пожалуйста, используйте полные имена, когда вы ссылаетесь на объекты и свойства. Будьте конкретны, приведите некоторый код или простые примеры. Не ждите от нас понимания отсутствующего контекста.

Ответы на вопрос(4)

что ты собираешься делать. Поэтому я постараюсь предоставить вам, я надеюсь, интересную информацию по этому вопросу.

Во-первых, давайте рассмотрим следующий UserControl в проекте программного обеспечения для управления клиентами.

public partial class CustomerManagementUserControl : UserControl {
    public CustomerManagementUserControl() {
        InitializeComponent();
        _customerBindingSource = new BindingSource();
    }
    public IList<ICustomer> DataSource {
        set {
            _customerBindingSource.DataSource = value;
        }
    }
    private BindingSource _customerBindingSource;
}

Во-вторых, давайте рассмотрим следующую форму, которая должна быть вашей формой управления клиентами.

public partial class CustomerManagementForm : Form {
    public CustomerManagementForm() {
        InitializeComponent();
        _customerUserControl = new CustomerManagementUserControl();
        _customerUserControl.Name = @"customerUserControl";
    }
    private void CustomerManagementForm_Load(object sender, EventArgs e) {
        // CustomersFacade is simply a static class providing customer management features and requirements.
        // Indeed, the GetCustomers() method shall return an IList<ICustomer>.
        // The IList type and typed IList<T> are both intended to be bindable as a DataSource for DataBinding.
        _customerUserControl.DataSource = CustomersFacade.GetCustomers();
        this.Controls.Add(_customerUserControl);
    }
    private CustomerManagementUserControl _customerUserControl;
}

Если вы планируете использовать свойство CustomerManagementUserControl.DataSource в окне «Свойства», попробуйте добавить следующее поверх определения своего свойства.

[System.ComponentModel.DesignTimeVisible(true), System.ComponentModel.DesignerCategory("CustomerUserControl"), System.ComponentModel.Description("Sets the CustomerUserControl DataSource property")]

Это один из способов сделать то, что, я думаю, вы могли бы сделать. С другой стороны, если вы хотите получить как можно более абстрактное значение, установив объект другого типа в качестве свойства UserControl.BindingSource.DataSource, то вам нужно будет написать метод, который мог бы определять тип объекта. объект прошел, затем связал свойства соответственно. Хороший способ, которым вы могли бы пойти, возможно, с помощью Reflection, если вам удобно работать с ним. Любым возможным способом, который вы можете себе представить, работая с такими функциями полиморфизма, вам придется написать себе интерфейс, который должны реализовать все ваши привязываемые объекты. Таким образом, вы избежите неизвестных имен свойств, и когда придет время привязать элементы управления вашего UserControl, вы сможете привязать правильное свойство к правильному элементу управления и так далее.

Давайте попробуем следующее:

public interface IEntity {
    double Id { get; set; }
    string Number { get; set; }
    string Firstname { get; set; }
    string Surname { get; set; }
    long PhoneNumber { get; set; }
}
public interface ICustomer : IEntity {
}
public interface ISupplier : IEntity {
    string Term { get; set; }
}
public sealed Customer : ICustomer {
    public Customer() {
    }
    public double Id { get; set; }
    public string Number { get; set; }
    public string Firstname { get; set; }
    public string Surname { get; set; }
    public long PhoneNumber { get; set; }    
}
public sealed Supplier : ISupplier {
    public Supplier() {
    }
    public double Id { get; set; }
    public string Number { get; set; }
    public string Firstname { get; set; }
    public string Surname { get; set; }
    public long PhoneNumber { get; set; }    
    public string Term { get; set; }
}

Учитывая приведенный выше код, вы можете использовать свойство DataSource вашего UserControl для связывания с IEntity, так что вашему свойству может понравиться это.

[System.ComponentModel.DesignTimeVisible(true), System.ComponentModel.DesignerCategory("CustomerUserControl"), System.ComponentModel.Description("Sets the CustomerUserControl DataSource property")]
public IList<IEntity> DataSource {
    set {
        _customerBindingSource.DataSource = value;
    }
}

Тем не менее, если вы хотите продвинуться еще дальше, вы можете просто предоставить свои свойства DataBindings элементов управления UserControl, чтобы установить их во время разработки. Учитывая это, вы захотите выставить свой BindingSource как общедоступное свойство, чтобы вы могли установить его и во время разработки, а затем выбрать свой DataMember из этого BindinSource.

Я надеюсь, что это поможет вам обоим немного или, по крайней мере, даст вам несколько треков для дальнейшего поиска.

вы можете найти источник привязки из родительской формы в событии load вашего пользовательского элемента управления или что-то в этом роде ...

Dim components As Reflection.FieldInfo = typ.GetField("components", Reflection.BindingFlags.DeclaredOnly Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)

Dim lstBindingSources As New List(Of BindingSource)
For Each obj As Object In components.Components
   Dim bindSource As BindingSource = TryCast(obj, BindingSource)
   If bindSource IsNot Nothing Then
      lstBindingSources.Add(bindSource)
   End If
Next
If lstBindingSources.Count = 1 Then
   MyBindingSource.DataSource = lstBindingSources(0).DataSource
End If

ых в двух источниках привязки, элементы управления не будут последовательно обновляться во втором источнике привязки. Возможно, компромисс с выбором, приведенным выше, заключается в следующем:

Временно добавьте источник привязки в usercontrol и используйтеVS дизайнер, чтобы установить привязки к элементам управления.принесиdesigner.vb в редакторе кода. Искать все"DataBindings.Add" линии, которые были созданы дизайнером. Скопируйте их все в блокнот.удалите источник связывания из конструктора и добавьте ссылку на источник связывания в коде. Добавьте свойство для источника привязки с тем же именем, которое использовалось в конструкторе. В установщике для свойства вставьте все строки из блокнота выше в шаге 2.В событии Load формы назначьте источник привязки формы свойству пользовательского элемента управления. Если пользовательский элемент управления встроен в другой пользовательский элемент управления, вы можете использовать событие handlecreated родительского элемента управления, чтобы сделать то же самое.

Там меньше печатать и меньше опечаток, потому чтоVS Дизайнер создает все эти буквенные имена свойств текста.

однако, это может быть полезно для кого-то еще, читающего этот пост.

У меня есть контроль наUserControl которые связаны с данными. Мне нужно иметьBindingSource наUserControl для того, чтобы иметь возможность связать элементы управления во время разработки. Реальность"BindingSourceОднако сидит наForm, Другими словами, элементы управления наUserControl должен вести себя так, как будто они сидят прямо на форме (или наContainerControl на форме).

Идея этого решения заключается в том, чтобы следить заDataSourceChanged Событие "Реал"BindingSource и назначить егоDataSource к местномуBindingSource когда это изменится. Для того, чтобы найти «настоящий»BindingSource Я позволилForm (или жеControl) содержащий его реализует следующий интерфейс:

public interface IDataBound
{
    BindingSource BindingSource { get; }
}

Мы можем наблюдать заParentChanged событие элемента управления, чтобы узнать, когда он был добавлен кForm илиContainerControl, Проблема в том, что этоContainerControl само по себе, возможно, не было добавлено кForm (или другойContainerControl) еще в это время. В этом случае мы подписываемся наParentChanged событие последнего родителя, которого мы находим в цепочке родителей, и ждем, пока этот последний родитель не будет добавлен, и так далее, пока мы не найдемControl или жеForm реализацииIDataBound, КогдаIDataBound был найден, мы подписываемся наDataSourceChanged событие егоBindingSource.

public partial class MyUserControl : UserControl
{
    private IDataBound _dataBoundControl;
    private Control _parent;

    public MyUserControl()
    {
        InitializeComponent();
        if (LicenseManager.UsageMode == LicenseUsageMode.Runtime) {
            _parent = this;
            SearchBindingSource();
        }
    }

    private void SearchBindingSource()
    {
        if (_parent != null && _dataBoundControl == null) {
            while (_parent.Parent != null) {
                _parent = _parent.Parent;
                _dataBoundControl = _parent as IDataBound;
                if (_dataBoundControl != null) {
                    if (_dataBoundControl.BindingSource != null) {
                        _dataBoundControl.BindingSource.DataSourceChanged +=
                            new EventHandler(DataBoundControl_DataSourceChanged);
                    }
                    return;
                }
            }
            // This control or one of its parents has not yet been added to a
            // container. Watch for its ParentChanged event.
            _parent.ParentChanged += new EventHandler(Parent_ParentChanged);
        }
    }

    void Parent_ParentChanged(object sender, EventArgs e)
    {
        SearchBindingSource();
    }

    void DataBoundControl_DataSourceChanged(object sender, EventArgs e)
    {
        localBindingSource.DataSource = _dataBoundControl.BindingSource.DataSource;
    }
}

Ваш ответ на вопрос