在.NET 4.5中使用c#和winforms我想将菜单项的Checked
属性与表单的Visible
属性相关联。
更改这两个属性中的任何一个都会改变另一个属性以使它们保持同步。
这样做有一个简单而优雅的解决方案吗?
答案 0 :(得分:1)
这个例子有一个复选框和一个按钮:
连接CheckedChanged事件
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
var checkBox = sender as CheckBox;
button1.Visible = !checkBox.Checked;
}
修改强>
好的,我误解了。
虽然解决了#farid'是一个干净的解决方案,使用viewmodel和模型分离关注点,它还为您的应用程序增加了更多的复杂性。
如果您不想使用此mvvm模式并将逻辑放在后面的代码中,则可以将INotifyPropertyChanged接口实现为具有visible属性的表单(或添加自定义事件),添加新的Visible设置base.visible属性(由Control类中的Form继承)并引发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;
}
}
答案 1 :(得分:0)
您可以使用Windows Forms Data Bindings。
每个Windows窗体控件都有一个DataBindings
属性,可用于将给定数据源中的属性绑定到控件属性之一。
您可以像下面的示例一样构建代码:
此示例显示从ViewModel
对象到控件属性的绑定。在您的特定情况下,您可以将ViewModel
属性绑定到两个控件属性。
public partial class StackOverflowForm : Form
{
public ViewModel Model { get; set; }
public Dictionary<string, Control> BindableControls { get; set; }
public StackOverflowForm()
{
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
方法注册简单绑定(参数很简单)。
&#39;视图模型&#39; class在INotifyPropertyChanged
中实现System.ComponentModel
接口。当ViewModel中的任何属性发生更改时,此接口会添加PropertyChanged
事件以进行调用。
在form的构造函数中,我在侦听器中向PropertyChanged
ViewModel
事件添加了事件侦听器。我强制绑定为绑定为其注册的每个控件读取新值。这部分代码刷新了绑定控件并更改了按钮的可见状态。
注意:为了回答简单性,我假设ViewModel
中绑定到控件属性的属性在表单控件中具有带目标属性的SAME名称。 (Mode.Visible和boundButton.Visible)。如果要为源和目标属性实现属性名称映射,可以使用Dictionary
或其他内容来实现此功能。