2009-06-11 3 views
10

BindingSource에 바인딩하려는 여러 필드가있는 UserControl이 있습니다. 또한 UserControl이 BindingSource 속성을 노출하여 Form에 놓을 수 있고 양식의 BindingSource에 바인딩 될 수 있기를 바랍니다. 이 작업을 수행하는 쉬운 방법이 있습니까? BindSource setter에서 UserControl의 모든 컨트롤을 다시 바인딩 할 수 있다는 것을 알고 있습니다. 그러나 이것은 잘못된 것처럼 보입니다. 폼에서 BindingSource에 사용자 정의 컨트롤의 BindingSource를 연결할 수있는 BindingSource 프록시가 있습니까?UserControl에서 BindingSource 사용

+0

DataSource를 호출 할 속성을 작성하면 BindingSource.DataSource 개체 속성이 노출 될 수 있으며 양식의 BindingSource.DataSource 속성이 설정됩니다. 그렇지 않다면, 당신이하고 싶은 것을 더 설명하거나, 더 잘 이해할 수 있도록 도와 줄 수있는 구체적인 예를 들어보십시오. 내가 읽었을 때 아직도 머리 속에 약간 흐릿 해져있다. 디자인 타임에 DataSource를 설정 하시겠습니까? 속성 창에서 BindingSource 속성을 노출 하시겠습니까? BindingSource의 n 변경 디자인에서 UserControl 컨트롤을 특정 DataMember에 바인딩 하시겠습니까? –

+3

다른 사람들이 귀하의 질문에 제공 한 답을 받아 들일 수 있습니까? 저는이 시간을 갖고 도움을 주던 사람들에게 감사하고 도움을 줄 수있는 좋은 방법이라고 생각합니다. –

+0

개체 및 속성을 참조 할 때 전체 이름을 사용하십시오. 구체적으로 몇 가지 코드 또는 간단한 예제를 제공하십시오. 우리가 누락 된 상황을 이해할 것을 기대하지 마십시오. – profimedica

답변

5

귀하의 질문에 따라, 나는 당신이하고자하는 것을 거의 얻을 수 없습니다. 따라서 나는 그 문제에 대한 흥미로운 정보를 제공하기 위해 최선을 다할 것입니다.

먼저 고객 관리 소프트웨어 프로젝트에서 다음 UserControl을 고려해 보겠습니다.

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

둘째로, 고객 관리 양식이어야하는 다음 양식을 고려해 보겠습니다. 당신은 속성 창 내에서 CustomerManagementUserControl.DataSource 속성을 사용하여 기대하는 경우

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

은 당신의 속성 정의의 상단에 다음과 같은 추가 고려하시기 바랍니다.

[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; } 
} 

위의 코드를 고려할 때, 당신은 당신의 재산은 다음과 같이 같은 수 있도록, IEntity과 결합하기 위해 해당 UserControl의 데이터 소스 속성을 사용할 수 있습니다. 당신이 더욱 밀어하고자하는 경우, 당신은 단지 디자인 타임에 그들을 설정하기 위해 사용자의 UserControl의 컨트롤의 데이터 바인딩 속성을 노출 할 수 말했다

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

. 이를 고려하여 BindingSource를 공개 속성으로 공개하여 디자인 타임에 설정할 수도 있으므로이 BindinSource에서 DataMember를 선택해야합니다.

이 정보가 조금이라도 또는 최소한 도움이 되었기를 바랍니다. 추가 검색을 위해 몇 가지 트랙을 제공하십시오. 당신이 당신의 사용자 컨트롤이나 그런 식의로드 이벤트에서 부모 폼에서 바인딩 소스를 찾을 수있는 모든 자동으로 수행하고자한다면

1

...

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 
1

동일한를 할당하는 경우 개체 참조를 두 바인딩 소스의 데이터 소스로 사용하면 두 번째 바인딩 소스에서 컨트롤이 일관되게 업데이트되지 않습니다.

  1. 이 일시적으로 UserControl을에 BindingSource에 추가하고 컨트롤에 바인딩을 설정 VS 디자이너를 사용 아마도 위의 선택에 타협은 다음과 같다.
  2. 코드 편집기에서 designer.vb을 불러 오십시오. 디자이너가 작성한 모든 "DataBindings.Add" 행을 검색하십시오. 메모장에 모두 복사하십시오.
  3. 디자이너에서 bindingsource를 삭제하고 코드에서 bindingsource 참조를 추가하십시오. 디자이너에서 사용 된 것과 동일한 이름의 바인딩 소스에 대한 속성을 추가하십시오. 속성 설정자에서 2 단계에서 위의 메모장에서 모든 줄을 붙여 넣습니다.
  4. 폼의 Load 이벤트에서 폼의 bindingsource를 사용자 정의 컨트롤의 속성에 할당합니다. 사용자 정의 컨트롤이 다른 사용자 정의 컨트롤에 포함 된 경우 부모 컨트롤의 handlecreated 이벤트를 사용하여 동일한 작업을 수행 할 수 있습니다.

VS 디자이너가 리터럴 텍스트 속성 이름을 모두 생성하기 때문에 타이핑이 적고 오타가 줄어 듭니다.

1

나는 그것이 늦은 대답이라는 것을 안다; 그러나이 게시물을 읽는 다른 사용자에게 유용 할 수 있습니다.

UserControl에 데이터 바인딩 된 컨트롤이 있습니다. 디자인 타임에 컨트롤을 바인딩하려면 UserControlBindingSource이 있어야합니다. 그러나 "진짜"BindingSourceForm에 있습니다. 즉, UserControl의 컨트롤은 양식 (또는 양식의 ContainerControl)에 직접 앉아있는 것처럼 동작해야합니다.

이 솔루션 뒤에 아이디어는 BindingSource "진짜"의 DataSourceChanged 이벤트를보고하고 변경할 때 지역 BindingSource에 그 DataSource를 할당하는 것입니다. BindingSource "진짜"를 찾기 위해 나는 할 수는 다음과 같은 인터페이스를 구현 포함 Form (또는 Control) :

public interface IDataBound 
{ 
    BindingSource BindingSource { get; } 
} 
우리가 추가 한 경우 알기 위해 컨트롤의 ParentChanged 이벤트를 볼 수 있습니다

Form 또는 ContainerControl. 문제는이 ContainerControl 자체가 현재 Form (또는 다른 ContainerControl)에 아직 추가되지 않았을 수 있다는 것입니다. 이 경우 부모 체인에서 찾은 마지막 부모의 ParentChanged 이벤트를 구독하고이 마지막 부모가 추가 될 때까지 기다리는 등 Control 또는 FormIDataBound이 될 때까지 기다립니다. 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; 
    } 
} 
관련 문제