【问题标题】:Copy the state of controls and variables from one Form to another in c#在c#中将控件和变量的状态从一个窗体复制到另一个窗体
【发布时间】:2016-07-21 05:48:19
【问题描述】:

我有一个 Windows 窗体。如果用户未选中复选框,则稍后按下一步时会打开一个新表单,但如果他们选择了它,则会使用相同的表单。
如果他们选中复选框,我希望出现当前表单的克隆(具有相同的变量和控制值),以便他们稍后可以更改值而无需取消选中复选框,然后再次按下一步,然后手动输入其他值。

Form duplicate = this; 只是引用相同的形式,没有 new(this) 这样的东西。
我无法尝试 Form duplicate = new Form() = this,因为我的表单采用了早期表单的构造函数

任何人都知道如何做到这一点?提前致谢

【问题讨论】:

  • 您是否有许多需要克隆的状态变量?克隆整个表单层次结构(控件、子元素和事件)对我来说似乎是一团糟,我建议你不要这样做。如果您要克隆 5 到 10 个控件的状态,最好坚持使用针对这些特定控件执行此操作的方法。
  • 什么方法用它们的值克隆控件(我只想复制.text的值)
  • 例如检查CheckBoxes
  • 您可以在表单中添加第二个构造函数,您可以在其中传递您需要的值。
  • 如何创建一个包含所有变量和所有文本框的.text 值的数组

标签: c# winforms reflection


【解决方案1】:

您可以在表单中添加这些方法:

public void RestoreState(Dictionary<string, object> controlStates, 
                         Dictionary<string, object> membersStates)
{
    InternalRestoreControls(controlStates);
    InternalRestoreMembers(membersStates);
}

private void InternalRestoreControls(Dictionary<string, object> states)
{
    foreach (var state in states)
    {
        Control c = this.Controls.Find(state.Key, true).FirstOrDefault();

        if (c is TextBox)
        {
            (c as TextBox).Text = state.Value == null ? null : state.Value.ToString();
        }
        else if (c is CheckBox)
        {
            (c as CheckBox).Checked = Convert.ToBoolean(state.Value);
        }
    }
}

private void InternalRestoreMembers(Dictionary<string, object> membersStates)
{
    // you might need to tweek this a little bit based on public/instance/static/private
    // but this is not the point of your question

    BindingFlags flags = BindingFlags.Instance | BindingFlags.Static
                       | BindingFlags.Public | BindingFlags.NonPublic;

    var props = this.GetType().GetProperties(flags);
    var fields = this.GetType().GetFields(flags);

    foreach(var variable in membersStates)
    {
        var prop = props.FirstOrDefault(x => x.Name == variable.Key);

        if(prop != null)
        {
            prop.SetValue(this, variable.Value);
            continue;
        }

        var field = fields.FirstOrDefault(x => x.Name == variable.Key);

        if(field != null)
        {
            field.SetValue(this, variable.Value);
            continue;
        }
    }
}

private Dictionary<string, object> GetControlsState()
{
    return new Dictionary<string, object>()
    {
        { txtBox1.Name, txtBox1.Text },
        // continue to the rest
    };
}

private Dictionary<string, object> GetMembersState()
{
    return new Dictionary<string, object>()
    {
        { nameof(variable1), variable1 },
        // continue to the rest
    };
}

用法:

Form duplicate = new Form();
duplicate.RestoreState(this.GetControlsState(), this.GetMembersState());

【讨论】:

    【解决方案2】:

    我会这样做: 假设您想用一个按钮打开“克隆”。 在 to 克隆形式中:

        public Form1()
        {
            InitializeComponent();
        }
    
        public Form1(string YourValue, int AnotherValue)     //This basically works like a constructor when the form is called
        {
            InitializeComponent();
            ValueLabel1.Text = YourValue;
            ValueLabel2.Text = Convert.ToString(AnotherValue);
        }
    
        private void DuplicateButton_Click(object sender, EventArgs e)
        {
            int a = 3;
            Form1 Window = new Form1(TextBox1.Text, a);
            Window.Show;
        }
    

    我希望这对你有用

    【讨论】:

    • 有大约 15 个文本框,我已经有其他目的的构造函数
    • 这有点复杂,但您可以使用属性TextBox1 TextBox2 等编写一个对象并给它们赋值。之后你将它保存为 xml,当你再次调用他的表单时,你会加载 xml 文件并为每个 TextBoxes 分配值。
    【解决方案3】:

    您可以使用字典,其中控件名称为键,控件值为值,并将其作为可选参数传递

    public form1(string para1, int para2, Dictionary<string,object>yourDic=null)
    {
    
    }
    

    【讨论】:

    • 是的,将您的控件名称和值(如文本或布尔值)保存在字典中。当您加载表单时,您可以检查字典是否为空。如果它不为空,您可以使用该值填充控件.
    猜你喜欢
    • 1970-01-01
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    • 2019-03-09
    • 1970-01-01
    • 2012-12-03
    相关资源
    最近更新 更多