C#动态表单(反射) - 链接控件

时间:2013-07-29 14:34:30

标签: c# mysql winforms reflection user-controls

对不起标题质量差。我想不出更好的方式来表达这一点。

对于我目前正与一些朋友合作的项目,我自己处于创建动态表单(带反射)的情况,我现在想要验证。

示例(忽略黑匣子,它包含现在不相关的旧表单元素,我不想让你们混淆):

Dynamic form with reflection

正如您可能已经猜到的那样,它是一个用于创建mysql数据库的应用程序。 这是我遇到问题的地方。如果选中其他人,我想禁用复选框。

例如:如果我选中“PrimaryKey”,我想禁用“Null”复选框。 从unsigned更改为signed会更改numericupdown最小值和最大值等。

但是通过反射和所有,我发现很难确切地知道禁用哪个复选框。 我希望你们有一些建议。

我一直在想这个问题,想到了一些想法。也许这些是比现在更好的解决方案。

思想1:我为每种数据类型创建UserControls。 Pro:没有反射问题,也很容易识别UserControl中的每个控件以进行验证。 Con's:Copy-Pasting,很多UserControls,有很多相同的控件。

思想2:对类的每个属性使用description标记做一些事情。在描述中创建规则,允许我将复选框链接在一起。在这里,我只需要将规则复制到每个类属性,然后就可以了。

我一直在考虑其他解决方案,但我没记住它们。 我希望你们能给我一些好的建议/建议。

[编辑] 也许我的代码可以解释一下。 我的代码:

PropertyInfo[] properties = DataTypes.DataTypes.GetTypeFromString(modelElement.DataType.ToString()).GetType().GetProperties();
        foreach (PropertyInfo prop in properties)
        {
            if (prop.Name != "Label" && prop.Name != "Project" && prop.Name != "Panel")
            {
                var value = prop.GetValue(modelElement.DataType, null);

                if (value != null)
                {
                    tableLayoutPanel1.Controls.Add(new Label { Text = prop.Name, Anchor = AnchorStyles.Left, AutoSize = true });

                    switch (value.GetType().ToString())
                    {
                        case "System.Int32":
                            NumericUpDown numericUpDown = new NumericUpDown();
                            numericUpDown.Text = value.ToString();
                            numericUpDown.Dock = DockStyle.None;
                            tableLayoutPanel1.Controls.Add(numericUpDown);

                            break;
                        case "System.Boolean":
                            CheckBox checkBox = new CheckBox();
                            checkBox.Dock = DockStyle.None;

                            // checkbox will become huge if not for these changes
                            checkBox.AutoSize = false;
                            checkBox.Size = new Size(16, 16);

                            if (value.Equals(true))
                            {
                                checkBox.CheckState = CheckState.Checked;
                            }
                            tableLayoutPanel1.Controls.Add(checkBox);

                            break;
                        default:
                            MessageBox.Show(@"The following type has not been implemented yet: " + value.GetType());

                            break;
                    }
                }
            }
        }

3 个答案:

答案 0 :(得分:1)

以下是我的评论中的模型:

// The ViewModel is responsible for handling the actual visual layout of the form.
public class ViewModel {

    // Fire this when your ViewModel changes
    public event EventHandler WindowUpdated;

    public Boolean IsIsNullCheckBoxVisible { get; private set; }

    // This method would contain the actual logic for handling window changes.
    public void CalculateFormLayout() {

        Boolean someLogic = true;

        // If the logic is true, set the isNullCheckbox to true
        if (someLogic) {
            IsIsNullCheckBoxVisible = true;
        }

        // Inform the UI to update
        UpdateVisual();
    }

    // This fires the 'WindowUpdated' event.
    public void UpdateVisual() {
        if (WindowUpdated != null) {
            WindowUpdated(this, new EventArgs());
        }
    }

}

public class TheUI : Form {

    // Attach to the viewModel;
    ViewModel myViewModel = new ViewModel();
    CheckBox isNullCheckBox = new CheckBox();

    public TheUI() {
        this.myViewModel.WindowUpdated += myViewModel_WindowUpdated;
    }

    void myViewModel_WindowUpdated(object sender, EventArgs e) {
        // Update the view here.

        // Notie that all we do in the UI is to update the visual based on the
        // results from the ViewModel;
        this.isNullCheckBox.Visible = myViewModel.IsIsNullCheckBoxVisible;
    }

}

这里的基本想法是确保用户界面尽可能少。它的作用应该是更新。更新什么?那是由ViewModel班来决定的。我们在ViewModel类中执行所有更新逻辑,然后在更新计算完成后,我们调用UpdateVisual()事件,该事件告诉UI它需要表示自己。发生WindowUpdated事件时,UI只会通过显示ViewModel设置的配置进行响应。

这可能看起来像是最初设置的很多工作,但是一旦到位,它将为您节省大量的时间。如果您有任何问题,请告诉我。

答案 1 :(得分:0)

尝试将一个复选框的事件关联以禁用另一个复选框;像这样的东西:

private void primaryKeyBox_AfterCheck(object sender, EventArgs e)
{
    nullBox.Enabled = false;
}

这是一个非常简单的例子,需要稍微修改一下,但我觉得你应该这样做。您还必须为未选中的框添加事件。您还需要逻辑来仅根据已检查和未检查的复选框从某些复选框获取数据。

对于所有其他事情,例如根据下拉列表更改数字,也可以根据事件进行更改。

答案 2 :(得分:-1)

对于WinForms,我会使用数据绑定。

创建一个对象并实现INotifyPropertyChanged并使用该对象。

然后,如果你有一个对象实例aObj:

要将姓氏属性绑定到表单上的文本框,请执行以下操作:

Private WithEvents txtLastNameBinding As Binding

txtLastNameBinding = New Binding("Text", aObj, "LastName", True, DataSourceUpdateMode.OnValidation, "")

txtLastName.DataBindings.Add(txtLastNameBinding)

在这里查看更多信息。 INotifyPropertyChanged