0

抱歉标题质量差。我想不出更好的表达方式。

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

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

带反射的动态形式

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

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

但是通过反射等等,我发现很难确切知道要禁用哪个复选框。希望大家给点建议。

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

想法 1:我为每种数据类型创建用户控件。Pro's:反射没有问题,并且可以轻松识别 UserControl 中的每个控件以进行验证。缺点:复制粘贴,大量用户控件,有很多相同的控件。

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

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

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

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;
                    }
                }
            }
        }
4

3 回答 3

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;
    }

}

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

最初设置这似乎需要做很多工作,但一旦到位,它将为您节省大量时间。如果您有任何问题,请告诉我。

于 2013-07-29T15:01:27.410 回答
0

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

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

这是一个非常简单的示例,必须进行一些更改,但是对于我认为您要问的内容,它应该可以工作。您还必须为未选中的框添加事件。您还需要逻辑来仅根据已选中和未选中的复选框从某些复选框中获取数据。

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

于 2013-07-29T14:43:33.400 回答
-1

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

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

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

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

Private WithEvents txtLastNameBinding As Binding

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

txtLastName.DataBindings.Add(txtLastNameBinding)

在这里查看更多信息。 INotifyPropertyChanged

于 2013-07-29T19:51:13.837 回答