C# 有没有一种简单的方法将两个对象属性链接在一起?

C# 有没有一种简单的方法将两个对象属性链接在一起?,c#,.net,properties,C#,.net,Properties,在.NET 4.5中使用c#和winforms,我想将菜单项的Checked属性与表单的Visible属性链接起来 更改这两个属性中的任何一个都会更改另一个以保持它们同步 有没有一个简单而优雅的解决方案 类似于此示例的内容,带有复选框和按钮: 连接到CheckedChanged事件 private void checkBox1_CheckedChanged(object sender, EventArgs e) { var checkBox = sender as

在.NET 4.5中使用c#和winforms,我想将菜单项的
Checked
属性与表单的
Visible
属性链接起来

更改这两个属性中的任何一个都会更改另一个以保持它们同步


有没有一个简单而优雅的解决方案

类似于此示例的内容,带有复选框和按钮:

连接到CheckedChanged事件

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        var checkBox = sender as CheckBox;
        button1.Visible = !checkBox.Checked;
    }
编辑:

好吧,我误解了

虽然“farid”的解决方案是一个干净的解决方案,使用viewmodel和model分离关注点,但它也为您的应用程序增加了更多的复杂性

如果不想使用此mvvm模式并将逻辑放在代码中,则可以对具有visible属性的窗体实现INotifyPropertyChanged接口(或添加自定义事件),添加一个新的visible属性来设置base.visible属性(由窗体从控件类继承)并引发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;
    }
}
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;
    }
}
Form2代码隐藏:

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;
    }
}
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窗体控件都有一个
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;
    }
使用
RegisterBinding
方法注册简单绑定(参数足够简单)

“ViewModel”类在
System.ComponentModel
中实现
INotifyPropertyChanged
接口。此接口添加了一个
PropertyChanged
事件,以便在ViewModel中的任何属性发生更改时调用

在窗体的构造函数中,我将事件侦听器添加到侦听器中
ViewModel
PropertyChanged
事件中,我强制绑定读取绑定为其注册的每个控件的新值。这部分代码刷新绑定控件并更改按钮的可见状态


注意:为了简单起见,我假设
ViewModel
中绑定到控件属性的属性与表单控件中的目标属性具有相同的名称。(Mode.Visible和boundButton.Visible)。如果要实现源属性和目标属性的属性名称映射,可以使用
字典
或其他工具来实现此功能

目前这不是一个选项。这是不够的,因为如果Visible属性发生更改,它将不会更新菜单项的Checked属性。这是一个看似复杂但并不十分优雅的解决方案。但它会起作用:-)