有没有一种简单的方法可以 link 两个对象 属性 在一起?
Is there an easy way to link two objects property together?
在 .NET 4.5 中使用 c# 和 winforms 我想 link 菜单项的 Checked
属性 和 Visible
属性一个表格。
更改这两个属性中的任何一个都会更改另一个属性以保持同步。
是否有一个简单而优雅的解决方案来做到这一点?
类似于这个带有复选框和按钮的示例:
连接到 CheckedChanged 事件
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
var checkBox = sender as CheckBox;
button1.Visible = !checkBox.Checked;
}
编辑:
好吧,我误会了。
虽然 'farid' 的解决方案是一个干净的解决方案,使用视图模型和模型分离了关注点,但它也增加了您的应用程序的复杂性。
如果您不想使用此 mvvm 模式并将逻辑放在后面的代码中,您可以将 INotifyPropertyChanged 接口实现到具有可见 属性 的表单(或添加自定义事件),添加一个新的 Visible 属性 来设置 base.visible 属性(由 Form 从 Control class 继承)并引发 PropertyChanged 事件。在包含菜单项的表单中,您可以连接事件并执行必要的逻辑来设置选中状态或执行其他操作。
这是一个例子:
Form1后面的代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}
private Form2 _frm2;
private void Form1_Load(object sender, EventArgs e)
{
_frm2 = new Form2();
_frm2.MdiParent = this;
_frm2.PropertyChanged += _frm2_PropertyChanged;
_frm2.Show();
}
void _frm2_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Visible")
{
showToolStripMenuItem.Checked = _frm2.Visible;
}
}
private void showToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
var menuItem = sender as ToolStripMenuItem;
if (_frm2 != null)
_frm2.Visible = menuItem.Checked;
}
}
Form2后面的代码:
public partial class Form2 : Form, INotifyPropertyChanged
{
public Form2()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
public new bool Visible
{
get
{
return base.Visible;
}
set
{
base.Visible = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Visible"));
}
}
private void hideButton_Click(object sender, EventArgs e)
{
Visible = false;
}
}
您可以使用 Windows Forms Data Bindings.
每个 windows 表单控件都有一个 DataBindings
属性,可用于将给定数据源中的 属性 绑定到控件属性之一。
您可以像下面的示例一样构建您的代码:
此示例显示了从 ViewModel
对象到控件 属性 的绑定。在您的特定情况下,您可以将 ViewModel
属性 绑定到两个控件 属性。
public partial class WhosebugForm : Form
{
public ViewModel Model { get; set; }
public Dictionary<string, Control> BindableControls { get; set; }
public WhosebugForm()
{
Model = new ViewModel();
Model.PropertyChanged += Model_PropertyChanged;
BindableControls = new Dictionary<string, Control>();
Model.Visible = false;
InitializeComponent();
RegisterBinding(boundButton, "Visible", Model, "Visible");
}
void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
foreach (var item in BindableControls)
{
NotifyChange(item.Value, e.PropertyName);
}
}
private void NotifyChange(Control control, string propertyName)
{
button1.DataBindings[propertyName].ReadValue();
}
private void RegisterBinding(Control control, string controlPropertyName, ViewModel _model, string modelPropertyName)
{
control.DataBindings.Add(controlPropertyName, _model, modelPropertyName, true, DataSourceUpdateMode.OnPropertyChanged);
BindableControls[control.Name] = control;
}
private void SetPropertyButton_Click(object sender, EventArgs e)
{
Model.Visible = true;
}
}
public class ViewModel : INotifyPropertyChanged
{
private bool _IsVisible;
public bool Visible
{
get
{
return _IsVisible;
}
set
{
_IsVisible = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Visible"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
我以用作控件的绑定数据源的形式定义了一个 ViewModel 对象。 (具有可见 属性)
private void RegisterBinding(Control control, string controlPropertyName, ViewModel _model, string modelPropertyName)
{
control.DataBindings.Add(controlPropertyName, _model, modelPropertyName, true, DataSourceUpdateMode.OnPropertyChanged);
BindableControls[control.Name] = control;
}
使用RegisterBinding
方法注册简单绑定(参数够简单)
'ViewModel' class 在 System.ComponentModel
中实现了 INotifyPropertyChanged
接口。此接口添加一个 PropertyChanged
事件以在 ViewModel 中的任何 属性 更改时调用。
在窗体的构造函数中,我将事件监听器添加到监听器中 ViewModel
的 PropertyChanged
事件,我强制绑定为绑定为其注册的每个控件读取新值。这部分代码刷新了绑定控件并改变了按钮的可见状态。
注意: 为了简单起见,我假设 ViewModel
中绑定到控件 属性 的属性与目标 [=49] 具有相同的名称=] 在表单控件中。 (Mode.Visible 和 boundButton.Visible)。如果你想为源属性和目标属性实现 属性 名称映射,你可以使用 Dictionary
或其他东西来实现此功能。
在 .NET 4.5 中使用 c# 和 winforms 我想 link 菜单项的 Checked
属性 和 Visible
属性一个表格。
更改这两个属性中的任何一个都会更改另一个属性以保持同步。
是否有一个简单而优雅的解决方案来做到这一点?
类似于这个带有复选框和按钮的示例:
连接到 CheckedChanged 事件
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
var checkBox = sender as CheckBox;
button1.Visible = !checkBox.Checked;
}
编辑:
好吧,我误会了。
虽然 'farid' 的解决方案是一个干净的解决方案,使用视图模型和模型分离了关注点,但它也增加了您的应用程序的复杂性。
如果您不想使用此 mvvm 模式并将逻辑放在后面的代码中,您可以将 INotifyPropertyChanged 接口实现到具有可见 属性 的表单(或添加自定义事件),添加一个新的 Visible 属性 来设置 base.visible 属性(由 Form 从 Control class 继承)并引发 PropertyChanged 事件。在包含菜单项的表单中,您可以连接事件并执行必要的逻辑来设置选中状态或执行其他操作。
这是一个例子:
Form1后面的代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}
private Form2 _frm2;
private void Form1_Load(object sender, EventArgs e)
{
_frm2 = new Form2();
_frm2.MdiParent = this;
_frm2.PropertyChanged += _frm2_PropertyChanged;
_frm2.Show();
}
void _frm2_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Visible")
{
showToolStripMenuItem.Checked = _frm2.Visible;
}
}
private void showToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
var menuItem = sender as ToolStripMenuItem;
if (_frm2 != null)
_frm2.Visible = menuItem.Checked;
}
}
Form2后面的代码:
public partial class Form2 : Form, INotifyPropertyChanged
{
public Form2()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
public new bool Visible
{
get
{
return base.Visible;
}
set
{
base.Visible = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Visible"));
}
}
private void hideButton_Click(object sender, EventArgs e)
{
Visible = false;
}
}
您可以使用 Windows Forms Data Bindings.
每个 windows 表单控件都有一个 DataBindings
属性,可用于将给定数据源中的 属性 绑定到控件属性之一。
您可以像下面的示例一样构建您的代码:
此示例显示了从 ViewModel
对象到控件 属性 的绑定。在您的特定情况下,您可以将 ViewModel
属性 绑定到两个控件 属性。
public partial class WhosebugForm : Form
{
public ViewModel Model { get; set; }
public Dictionary<string, Control> BindableControls { get; set; }
public WhosebugForm()
{
Model = new ViewModel();
Model.PropertyChanged += Model_PropertyChanged;
BindableControls = new Dictionary<string, Control>();
Model.Visible = false;
InitializeComponent();
RegisterBinding(boundButton, "Visible", Model, "Visible");
}
void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
foreach (var item in BindableControls)
{
NotifyChange(item.Value, e.PropertyName);
}
}
private void NotifyChange(Control control, string propertyName)
{
button1.DataBindings[propertyName].ReadValue();
}
private void RegisterBinding(Control control, string controlPropertyName, ViewModel _model, string modelPropertyName)
{
control.DataBindings.Add(controlPropertyName, _model, modelPropertyName, true, DataSourceUpdateMode.OnPropertyChanged);
BindableControls[control.Name] = control;
}
private void SetPropertyButton_Click(object sender, EventArgs e)
{
Model.Visible = true;
}
}
public class ViewModel : INotifyPropertyChanged
{
private bool _IsVisible;
public bool Visible
{
get
{
return _IsVisible;
}
set
{
_IsVisible = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Visible"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
我以用作控件的绑定数据源的形式定义了一个 ViewModel 对象。 (具有可见 属性)
private void RegisterBinding(Control control, string controlPropertyName, ViewModel _model, string modelPropertyName)
{
control.DataBindings.Add(controlPropertyName, _model, modelPropertyName, true, DataSourceUpdateMode.OnPropertyChanged);
BindableControls[control.Name] = control;
}
使用RegisterBinding
方法注册简单绑定(参数够简单)
'ViewModel' class 在 System.ComponentModel
中实现了 INotifyPropertyChanged
接口。此接口添加一个 PropertyChanged
事件以在 ViewModel 中的任何 属性 更改时调用。
在窗体的构造函数中,我将事件监听器添加到监听器中 ViewModel
的 PropertyChanged
事件,我强制绑定为绑定为其注册的每个控件读取新值。这部分代码刷新了绑定控件并改变了按钮的可见状态。
注意: 为了简单起见,我假设 ViewModel
中绑定到控件 属性 的属性与目标 [=49] 具有相同的名称=] 在表单控件中。 (Mode.Visible 和 boundButton.Visible)。如果你想为源属性和目标属性实现 属性 名称映射,你可以使用 Dictionary
或其他东西来实现此功能。