Я знаю, что это немного поздно, но у меня возникла та же проблема - элемент управления, к которому я хочу привязаться, установлен на visible = false, когда отображается форма. Возможно, я хочу сделать это во многих формах, и я всегда неохотно пишу код для каждой привязки.
Итак, я собрал небольшой хак.
У меня есть форма с панелью, в которой я установил Visible = false в конструкторе. Я хочу связать представление с пользовательской моделью представления, которую я написал. В форме я добавляю BindingSource из панели инструментов. I DataSource источника привязки к источнику данных проекта для моей модели представления.
В таком случае идея состоит в том, чтобы перебирать элементы управления в форме и обновлять связанное значение элементов управления из источника данных (который является моделью представления).
Для этого я сохраняю видимое значение элемента управления, устанавливаю его в значение false и считываю значение привязки. Затем восстановите исходное видимое значение. Это делается с помощью метко названного метода HackIt ().
Вот код:
ViewModel
public class SimpleViewModel // : DomainModelBase - add your notify property changed
{
public SimpleViewModel()
{
_visible = true;
}
private bool _visible;
public bool Visible
{
get
{
return _visible;
}
set
{
_visible = value;
OnPropertyChanged("Visible");
}
}
}
Код конструктора форм
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.panel1 = new System.Windows.Forms.Panel();
this.bindingSource1 = new System.Windows.Forms.BindingSource(this.components);
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).BeginInit();
this.SuspendLayout();
//
// panel1
//
this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0)))));
this.panel1.DataBindings.Add(new System.Windows.Forms.Binding("Visible", this.bindingSource1, "Visible", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
this.panel1.Location = new System.Drawing.Point(94, 85);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(200, 100);
this.panel1.TabIndex = 0;
//
// bindingSource1
//
this.bindingSource1.DataSource = typeof(WindowsFormsBindVisible.SimpleViewModel);
//
// button1
//
this.button1.Location = new System.Drawing.Point(74, 34);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// button2
//
this.button2.Location = new System.Drawing.Point(155, 34);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 2;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(500, 261);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.panel1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.BindingSource bindingSource1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
}
Код формы
public partial class Form1 : Form
{
public SimpleViewModel ViewModel = new SimpleViewModel();
public Form1()
{
InitializeComponent();
this.panel1.Visible = false;
this.bindingSource1.DataSource = this.ViewModel;
}
private void Form1_Load(object sender, EventArgs e)
{
HackIt();
}
void HackIt()
{
this.SuspendLayout();
foreach(Control control in this.Controls)
{
var v = control.Visible;
control.Visible = true;
foreach(Binding db in control.DataBindings)
{
db.ReadValue();
}
control.Visible = v;
}
this.ResumeLayout();
}
}
С приведенным выше кодом форма запускается и показывает мой контроль. Вы можете изменить конструктор модели представления и по умолчанию установить false, чтобы скрыть. Это работает в любом случае.
В конструкторе формы - я хочу явно скрыть панель (this.panel1.Visible = false) - просто чтобы подтвердить привязку, когда модель представления по умолчанию visible = true, элемент управления корректно отображается при загрузке.
Затем мы можем заставить кнопки изменять видимое на модели представления, что переключит состояние видимой панели:
private void button1_Click(object sender, EventArgs e)
{
this.ViewModel.Visible = false;
}
private void button2_Click(object sender, EventArgs e)
{
this.ViewModel.Visible = true;
}
UPDATE
Это заставило меня преодолеть первое препятствие. Однако я использую компоненты Telerik, поэтому я решил отказаться от элемента управления Telerik на форме. Это полностью сломало все.
Вместо метода HackIt, указанного выше, вызовите следующую функцию RefreshDataBindings () в событии загрузки.
Я решил перебрать все элементы управления в форме и вручную обновить привязку отражающим способом. Это безумие! Но это работает на 100% - даже с контролем Telerik на моей форме. И производительность в моем основном приложении нормальная. Это просто грязный хак - но я поместил его один раз в базовую форму или базовый контроль - и я не беспокоюсь о своих привязках.
protected void RefreshDataBindings()
{
foreach (Control control in this.Controls)
RefreshControlBindingsRecursive(control);
}
private void RefreshControlBindingsRecursive(Control control)
{
if (!control.Visible || !control.Created)
{
foreach (Binding db in control.DataBindings)
{
if (db.PropertyName == "Visible")
{
try
{
object dataSource = db.DataSource is BindingSource ?
(db.DataSource as BindingSource).DataSource : db.DataSource;
PropertyInfo pi =
dataSource.GetType().GetProperty(db.BindingMemberInfo.BindingMember); ;
PropertyInfo piC = db.Control.GetType().GetProperty(db.PropertyName);
piC.SetValue(db.Control, pi.GetValue(dataSource));
}
catch (Exception ex)
{
string s = ""; // not bothered its too late at night
}
}
}
}
foreach (Control child in control.Controls)
RefreshControlBindingsRecursive(child);
}