BindingSource にバインドしたい複数のフィールドを持つ UserControl があります。また、フォームにドロップしてフォームの BindingSource にバインドできるように、UserControl に BindingSource プロパティを公開してもらいたいと思います。これを行う簡単な方法はありますか?BindSource セッターで UserControl のすべてのコントロールを再バインドできることがわかりました。しかし、これは間違っているようです。ユーザー コントロールの BindingSource をフォームの BindingSource にリンクできる BindingSource プロキシはありますか?
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")]
これは、あなたがやりたいと思うことを行う1つの方法です。一方、UserControl.BindingSource.DataSource プロパティとして別のタイプのオブジェクトを設定することで、可能な限り抽象的なオブジェクトを取得したい場合は、そのタイプを検出できるメソッドを作成する必要があります。オブジェクトが渡され、それに応じてプロパティがバインドされます。おそらく、作業に慣れている場合は、リフレクションを使用することをお勧めします。このようなポリモーフィズム機能を使用することを想像できるあらゆる方法で、バインド可能なすべてのオブジェクトを実装する必要があるインターフェイスを自分で作成する必要があります。このようにして、不明なプロパティ名を回避し、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; }
}
上記のコードを考慮すると、UserControl の DataSource プロパティを使用して 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;
}
}
つまり、さらにプッシュしたい場合は、UserControl のコントロールの DataBindings プロパティを公開して、デザイン時に設定することができます。これを考慮して、BindingSource をパブリック プロパティとして公開し、設計時にも設定できるようにしてから、この BindinSource から DataMember を選択します。
これが少しでも、または少なくとも、さらに検索するためのいくつかのトラックを提供するのに役立つことを願っています.
私はそれが遅い答えであることを知っています。ただし、この投稿を読んでいる他の人にとっては役立つかもしれません。
UserControlデータにバインドされたコントロールがあります。デザイン時にコントロールをバインドできるようにするには、BindingSourceをオンにする必要があります。ただし、UserControl「本物」は上にあります。つまり、 上のコントロールは、フォーム (またはフォーム上) に直接置かれているかのように動作する必要があります。BindingSourceFormUserControlContainerControl
このソリューションの背後にあるアイデアDataSourceChangedは、「本物」のイベントを監視し、それが変更されたときにそれをローカルBindingSourceに割り当てることです。「本物」を見つけるために、それを含む(または) に次のインターフェースを実装させます。DataSourceBindingSourceBindingSourceFormControl
public interface IDataBound
{
BindingSource BindingSource { get; }
}
コントロールが または にいつ追加されたかParentChangedを知るために、コントロールのイベントを監視できます。ここでの問題は、この時点でこれ自体が(または別の) にまだ追加されていない可能性があることです。この場合、親チェーンで見つけた最後の親のイベントをサブスクライブし、この最後の親が追加されるまで待ちます。が見つかったら、その のイベントをサブスクライブします。FormContainerControlContainerControlFormContainerControlParentChangedControlFormIDataBoundIDataBoundDataSourceChangedBindingSource
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;
}
}
これをすべて自動的に行いたい場合は、ユーザーコントロールのロードイベントなどで親フォームからバインディングソースを探すことができます...
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
2 つのバインディング ソースのデータ ソースと同じオブジェクト参照を割り当てた場合、コントロールは 2 番目のバインディング ソースで一貫して更新されません。おそらく、上記の選択肢に対する妥協案は次のとおりです。
- ユーザー コントロールにバインディングソースを一時的に追加し、
VSデザイナーを使用してバインディングをコントロールに設定します。 - を
designer.vbコード エディターに表示します。"DataBindings.Add"デザイナーが作成したすべてのラインを検索します。それらをすべてメモ帳にコピーします。 - デザイナーから bindingsource を削除し、コードに bindingsource 参照を追加します。デザイナーで使用されたのと同じ名前でバインディングソースのプロパティを追加します。プロパティのセッターに、上記の手順 2 のメモ帳のすべての行を貼り付けます。
- フォームの Load イベントで、フォームの bindingsource をユーザー コントロールのプロパティに割り当てます。ユーザー コントロールが別のユーザー コントロールに埋め込まれている場合は、親コントロールの handlecreated イベントを使用して同じことを行うことができます。
VSデザイナーがすべてのリテラル テキスト プロパティ名を作成しているため、入力とタイプミスが少なくなります。