创建一个包含客户指定的其他动态字段的表单,选项?

时间:2011-01-10 13:30:10

标签: .net wpf winforms forms dynamic

我们有一个桌面应用程序,它基本上为特定部门(例如交通工具)创建作业日期,参考,驱动程序分配等工作,然后发送到PDA或从PDA发送以进行状态更新。

虽然它主要是现成的,但我们通常最终不得不做适合公司的定制部件,大约90%的时间它只有额外的数据字段不需要任何逻辑,只能存储/检索。

我一直在寻找一个基本的拖放库来将表单转换为可编辑的模式,我可以保存位置,组件类型,默认值并在非编辑模式下在运行时填充但实际上并没有能够找到一个。

是我自己滚动的最好方法,还是我错过了一个可以让我获得60%路径的图书馆? WPF或Winforms帮助将不胜感激(我们正在使用Winforms但转向WPF)。

干杯,

托马斯

1 个答案:

答案 0 :(得分:0)

我建议你自己写一下。在带有标签控件垂直列表的表单的最基本情况下,我的直观方法是拥有一个数据对象,该对象由一个有序的字符串对象列表组成(也可以使其成为带有验证规则的三元组),当应该加载表单时,检查每个对象的类型,如果它是一个字符串,你创建一个文本框,如果它是一个bool,你创建一个复选框等。 如果您有int和double,例如,您也可以进行输入验证。另一个方向也不应该太难 我之前编写了半动态通用编辑对话框,如下所示(WPF): 窗口内容XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
    </Grid.RowDefinitions>
    <StackPanel Name="StackPanelInput" Grid.Row="0" Orientation="Vertical" VerticalAlignment="Top" Margin="5"/>
    <StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="5">
        <Button Name="ButtonOK" HorizontalAlignment="Right" Width="100" Margin="5" Click="ButtonOK_Click" IsDefault="True">OK</Button>
        <Button Name="ButtonCancel" HorizontalAlignment="Right" Width="100" Margin="5" Click="ButtonCancel_Click" IsCancel="True">Cancel</Button>
    </StackPanel>
</Grid>

代码隐藏:

public partial class EditDialog : Window
    {
        private List<Control> Controls = new List<Control>();

        public EditDialog()
        {
            InitializeComponent();
            Loaded += delegate { KeyboardFocusFirstControl(); };
        }

        public EditDialog(string dialogTitle) : this()
        {
            Title = dialogTitle;
        }

        private void ButtonOK_Click(object sender, RoutedEventArgs e)
        {
            (sender as Button).Focus();
            if (!IsValid(this))
            {
                MessageBox.Show("Some inputs are currently invalid.");
                return;
            }
            DialogResult = true;
        }

        private void ButtonCancel_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
        }

        bool IsValid(DependencyObject node)
        {
            if (node != null)
            {
                bool isValid = !Validation.GetHasError(node);
                if (!isValid)
                {
                    if (node is IInputElement) Keyboard.Focus((IInputElement)node);
                    return false;
                }
            }
            foreach (object subnode in LogicalTreeHelper.GetChildren(node))
            {
                if (subnode is DependencyObject)
                {
                    if (IsValid((DependencyObject)subnode) == false) return false;
                }
            }
            return true;
        }

        public TextBox AddTextBox(string label, ValidationRule validationRule)
        {
            Grid grid = new Grid();
            grid.Height = 25;
            grid.Margin = new Thickness(5);
            ColumnDefinition colDef1 = new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) };
            ColumnDefinition colDef2 = new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) };
            grid.ColumnDefinitions.Add(colDef1);
            grid.ColumnDefinitions.Add(colDef2);

            Label tbLabel = new Label() { Content = label };
            tbLabel.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
            grid.Children.Add(tbLabel);

            TextBox textBox = new TextBox();

            Binding textBinding = new Binding("Text");
            textBinding.Source = textBox;
            textBinding.ValidationRules.Add(validationRule);
            textBox.SetBinding(TextBox.TextProperty, textBinding);

            textBox.GotKeyboardFocus += delegate { textBox.SelectAll(); };
            textBox.TextChanged += delegate { textBox.GetBindingExpression(TextBox.TextProperty).ValidateWithoutUpdate(); };

            textBox.Text = "";
            textBox.GetBindingExpression(TextBox.TextProperty).ValidateWithoutUpdate();

            Grid.SetColumn(textBox, 1);
            grid.Children.Add(textBox);

            StackPanelInput.Children.Add(grid);
            Controls.Add(textBox);
            return textBox;
        }

        public TextBox AddTextBox(string label, ValidationRule validationRule, string defaultText)
        {
            TextBox tb = AddTextBox(label, validationRule);
            tb.Text = defaultText;
            return tb;
        }

        public CheckBox AddCheckBox(string label)
        {
            Grid grid = new Grid();
            grid.Height = 25;
            grid.Margin = new Thickness(5);

            CheckBox cb = new CheckBox();
            cb.VerticalAlignment = System.Windows.VerticalAlignment.Center;
            cb.Content = label;

            grid.Children.Add(cb);

            StackPanelInput.Children.Add(grid);
            Controls.Add(cb);
            return cb;
        }

        private void KeyboardFocusFirstControl()
        {
            if (Controls.Count > 0)
            {
                Keyboard.Focus(Controls[0]);
            }
        }
    }

用法示例:

EditDialog diag = new EditDialog();
TextBox firstName = diag.AddTextBox("First Name:", new StringValidationRule());
TextBox lastName = diag.AddTextBox("Last Name:", new StringValidationRule());
TextBox age = diag.AddTextBox("Age:", new IntegerValidationRule(1,int.MaxValue));
if ((bool)diag.ShowDialog())
{
    //parse texts and write them to some data;
}

使用一些自定义构造函数,编辑按钮等,我相信您将能够将其转换为完全动态的对话框。取决于布局应该多么复杂或多或少的工作。当然找到一个最简单的库,也许其他人都知道一个。