我知道这有点晚了,但我遇到了同样的问题 - 当显示表单时,我要绑定的控件设置为 visible = false。我可能想在很多表单上执行此操作,但我总是不愿意为每个绑定编写大量代码。
所以我整理了一个小技巧。
我有一个带有面板的表单,我在构造函数中将其设置为 Visible = false。我想将视图绑定到我编写的自定义视图模型。在表单中,我从工具箱中放入了一个 BindingSource。我将数据源的绑定源绑定到我的视图模型的项目数据源。
然后想法是遍历表单上的控件,并从数据源(即视图模型)更新控件绑定值。
为此,我存储了控件的可见值,将其设置为 false,然后读取绑定值。然后恢复初始可见值。这是在恰当命名的方法 HackIt() 中完成的。
代码如下:
视图模型
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)——只是为了证明当视图模型默认可见=真时的绑定,控件在加载时正确显示。
然后我们可以让按钮改变视图模型上的可见性,这将切换面板的可见状态:
private void button1_Click(object sender, EventArgs e)
{
this.ViewModel.Visible = false;
}
private void button2_Click(object sender, EventArgs e)
{
this.ViewModel.Visible = true;
}
更新
这让我克服了第一个障碍。但是,我使用的是 Telerik 组件,所以我决定在表单上放置一个 Telerik 控件。这完全破坏了一切。
代替上面的 HackIt 方法,在 load 事件中调用下面的 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);
}