为Wpf敏捷开发做准备-Wpf实现Form表单2

AIStudio框架汇总及介绍

前言:上一节实现的FormItem中,还需要自己写TextBox或者ComboBox,代码还是比较多,我们能不能设置一个属性,让其自动生成呢?说干就干。

第一步:实现FormCodeItem继承FormItem,定义依赖性属性ControlType,根据ControlType自动生成控件,思路很明确,代码很多。

#region ControlType
public static readonly DependencyProperty ControlTypeProperty = DependencyProperty.Register(
    "ControlType", typeof(FormControlType), typeof(FormCodeItem), new PropertyMetadata(FormControlType.TextBox, OnControlTypeChanged));

private static void OnControlTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (d is FormCodeItem formCodeItem)
    {
        formCodeItem.GetControl((FormControlType)e.NewValue);
    }
}

[DisplayName("控件类型")]
public FormControlType ControlType
{
    get
    {
        return (FormControlType)GetValue(ControlTypeProperty);
    }
    set
    {
        SetValue(ControlTypeProperty, value);
    }
}

private void GetControl(FormControlType controlType)
{
    if (_contentPresenter == null)
        return;

    bool hideHeader = false;

    
    switch (controlType)
    {
        case FormControlType.TextBox:
            {
                _control = new TextBox() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(TextBox.TextProperty, binding);
                }
                break;
            }
        case FormControlType.ComboBox:
            {
                _control = new ComboBox() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(ComboBox.SelectedValueProperty, binding);
                }
                _control.SetValue(ComboBox.DisplayMemberPathProperty, "Text");
                _control.SetValue(ComboBox.SelectedValuePathProperty, "Value");
                break;
            }
        case FormControlType.PasswordBox:
            {
                _control = new PasswordBox() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(PasswordBoxBindingBehavior.PasswordProperty, binding);
                }
                break;
            }
        case FormControlType.DatePicker:
            {
                _control = new DatePicker() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(DatePicker.SelectedDateProperty, binding);
                }
                break;
            }
        case FormControlType.TreeSelect:
            {
                _control = new TreeSelect() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.Mode = BindingMode.TwoWay;
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(TreeSelect.SelectedValueProperty, binding);
                }
                _control.SetValue(TreeSelect.DisplayMemberPathProperty, "Text");
                _control.SetValue(TreeSelect.SelectedValuePathProperty, "Value");

                var dataTemplate = new HierarchicalDataTemplate();
                dataTemplate.ItemsSource = new Binding("Children");
                FrameworkElementFactory fef = new FrameworkElementFactory(typeof(TextBlock));
                Binding bind = new Binding("Text");
                fef.SetBinding(TextBlock.TextProperty, bind);
                dataTemplate.VisualTree = fef;
                (_control as TreeSelect).ItemTemplate = dataTemplate;
                break;
            }
        case FormControlType.MultiComboBox:
            {
                _control = new MultiComboBox() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.Mode = BindingMode.TwoWay;
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(CustomeSelectionValues.SelectedValuesProperty, binding);
                }
                _control.SetValue(ComboBox.DisplayMemberPathProperty, "Text");
                _control.SetValue(ComboBox.SelectedValuePathProperty, "Value");
                break;
            }
        case FormControlType.MultiTreeSelect:
            {
                _control = new TreeSelect() { Background = Brushes.Transparent, IsMulti = true };

                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.Mode = BindingMode.TwoWay;
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(TreeSelect.SelectedValuesProperty, binding);
                }
                _control.SetValue(TreeSelect.DisplayMemberPathProperty, "Text");
                _control.SetValue(TreeSelect.SelectedValuePathProperty, "Value");

                var dataTemplate = new HierarchicalDataTemplate();
                dataTemplate.ItemsSource = new Binding("Children");
                FrameworkElementFactory fef = new FrameworkElementFactory(typeof(StackPanel));
                fef.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);

                FrameworkElementFactory checkbox_fef = new FrameworkElementFactory(typeof(CheckBox));
                fef.AppendChild(checkbox_fef);
                Binding checkbox_bind = new Binding("IsChecked");
                checkbox_fef.SetBinding(CheckBox.IsCheckedProperty, checkbox_bind);

                FrameworkElementFactory textblock_fef = new FrameworkElementFactory(typeof(TextBlock));
                fef.AppendChild(textblock_fef);
                Binding textblock_bind = new Binding("Text");
                textblock_fef.SetBinding(TextBlock.TextProperty, textblock_bind);
                textblock_fef.SetValue(TextBlock.MarginProperty, new Thickness(2, 0, 0, 0));

                dataTemplate.VisualTree = fef;
                (_control as TreeSelect).ItemTemplate = dataTemplate;
                break;
            }
        case FormControlType.IntegerUpDown:
            {
                _control = new IntegerUpDown() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(IntegerUpDown.ValueProperty, binding);
                }
                break;
            }
        case FormControlType.LongUpDown:
            {
                _control = new LongUpDown() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(IntegerUpDown.ValueProperty, binding);
                }
                break;
            }
        case FormControlType.DoubleUpDown:
            {
                _control = new DoubleUpDown() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(IntegerUpDown.ValueProperty, binding);
                }
                break;
            }
        case FormControlType.DecimalUpDown:
            {
                _control = new DecimalUpDown() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(IntegerUpDown.ValueProperty, binding);
                }
                break;
            }
        case FormControlType.DateTimeUpDown:
            {
                _control = new DateTimeUpDown() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(IntegerUpDown.ValueProperty, binding);
                }
                break;
            }
        case FormControlType.CheckBox:
            {
                _control = new CheckBox() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(CheckBox.IsCheckedProperty, binding);
                }
                break;
            }
        case FormControlType.ToggleButton:
            {
                _control = new ToggleButton() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(ToggleButton.IsCheckedProperty, binding);
                }
                break;
            }
        case FormControlType.RichTextBox:
            {
                _control = new RichTextBox() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(RichTextBox.TextProperty, binding);
                }
                break;
            }
        case FormControlType.UploadFile:
            {
                _control = new UploadFile() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(UploadFile.FileProperty, binding);
                }
                _control.SetValue(UploadFile.UploadUrlProperty, ExtField1);
                _control.SetValue(UploadFile.UploadTokenProperty, ExtField2);
                break;
            }
        case FormControlType.UploadImage:
            {
                _control = new UploadFile() { Background = Brushes.Transparent };
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(UploadFile.FileProperty, binding);
                    _control.SetValue(UploadFile.UploadFileTypeProperty, UploadFileType.Image);
                }
                _control.SetValue(UploadFile.UploadUrlProperty, ExtField1);
                _control.SetValue(UploadFile.UploadTokenProperty, ExtField2);
                break;
            }
        case FormControlType.DataGrid:
            {
                _control = new DataGrid() { Background = Brushes.Transparent };
                (_control as DataGrid).IsReadOnly = true;
                if (!string.IsNullOrEmpty(Path))
                {
                    Binding binding = new Binding(Path);
                    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                    binding.ValidatesOnExceptions = true;
                    binding.ValidatesOnDataErrors = true;
                    binding.NotifyOnValidationError = true;
                    _control.SetBinding(DataGrid.ItemsSourceProperty, binding);
                }

                if (ExtField1 is IEnumerable<DataGridColumn> columns)
                {
                    if (columns != null)
                    {
                        foreach (var column in columns)
                        {
                            var copy = System.Windows.Markup.XamlReader.Parse(System.Windows.Markup.XamlWriter.Save(column)) as DataGridColumn;
                            (_control as DataGrid).Columns.Add(copy);
                        }
                    }
                }
                else if (ExtField1 is IEnumerable<DataGridColumnConfig> columnconfigs)
                {
                    if (columnconfigs != null)
                    {
                        foreach (var columnconfig in columnconfigs)
                        {
                            (_control as DataGrid).Columns.Add(columnconfig.GetColumn());
                        }
                    }
                }
                else
                {
                    (_control as DataGrid).Columns.Add(new DataGridTextColumn()
                    {
                        Binding = new Binding("Field1"),
                        Header = "字段1",
                        Width = new DataGridLength(100, DataGridLengthUnitType.Pixel)
                    });
                    (_control as DataGrid).Columns.Add(new DataGridTextColumn()
                    {
                        Binding = new Binding("Field2"),
                        Header = "字段2",
                        Width = new DataGridLength(100, DataGridLengthUnitType.Pixel)
                    });
                    (_control as DataGrid).Columns.Add(new DataGridTextColumn()
                    {
                        Binding = new Binding("Field3"),
                        Header = "字段3",
                        Width = new DataGridLength(100, DataGridLengthUnitType.Pixel)
                    });
                    (_control as DataGrid).Columns.Add(new DataGridTextColumn()
                    {
                        Binding = new Binding("Field4"),
                        Header = "字段4",
                        Width = new DataGridLength(100, DataGridLengthUnitType.Pixel)
                    });
                }

                _control.SetValue(DataGridColumnsConfigAttach.ShowConfigProperty, true);
                break;
            }
        case FormControlType.Query:
        case FormControlType.Submit:
            {
                hideHeader = true;

                _control = new Button();
                Binding binding = new Binding($"DataContext.{Path}");
                binding.RelativeSource = new RelativeSource { AncestorType = typeof(UserControl), Mode = RelativeSourceMode.FindAncestor };
                _control.SetBinding(Button.CommandProperty, binding);
                Binding binding2 = new Binding(".");
                _control.SetBinding(Button.CommandParameterProperty, binding2);
                Binding binding3 = new Binding("Header");
                binding3.Source = this;
                _control.SetBinding(Button.ContentProperty, binding3);
                break;
            }
        default:
            {
                _control = null;
                break;
            }      

       
    }

    if (_header != null)
    {
        _header.Visibility = hideHeader ? Visibility.Collapsed : Visibility.Visible;
    }

    if (_control != null)
    {
        _control.SetCurrentValue(ControlAttach.ClearTextButtonProperty, true);
        _contentPresenter.Content = _control;
    }

    SetItemsSource(ItemsSource);
}
#endregion

需要生成什么控件就需要定义一个类型,然后在cs中添加代码。

第二步:样式实现

<Style x:Key="AIStudio.Styles.FormCodeItem" BasedOn="{StaticResource AIStudio.Styles.FormItem}" TargetType="controls:FormCodeItem">
      <Style.Resources>
          <Style TargetType="{x:Type Button}" BasedOn="{StaticResource AIStudio.Styles.Button}" />
          <Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource AIStudio.Styles.CheckBox}" />
          <Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource AIStudio.Styles.ComboBox.Underline}" />
          <Style TargetType="{x:Type DatePicker}" BasedOn="{StaticResource AIStudio.Styles.DatePicker.Underline}" />
          <Style TargetType="{x:Type PasswordBox}" BasedOn="{StaticResource AIStudio.Styles.PasswordBox.Underline}" />
          <Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource AIStudio.Styles.RadioButton}" />
          <Style TargetType="{x:Type RichTextBox}" BasedOn="{StaticResource AIStudio.Styles.RichTextBox.Underline}" />
          <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource AIStudio.Styles.TextBox.Underline}" />
          <Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource AIStudio.Styles.ToggleButton.Switch}" />
          <Style TargetType="{x:Type controls:TreeSelect}" BasedOn="{StaticResource AIStudio.Styles.TreeSelect.Underline}" />
          <Style TargetType="{x:Type controls:MultiComboBox}" BasedOn="{StaticResource AIStudio.Styles.MultiComboBox.Underline}" />
          <Style TargetType="{x:Type controls:UploadFile}" BasedOn="{StaticResource AIStudio.Styles.UploadFile.Underline}" />
          <Style TargetType="{x:Type controls:RichTextBox}" BasedOn="{StaticResource AIStudio.Styles.RichTextBox.Underline}" />
      </Style.Resources>
  </Style>

这样,生成的控件样式也就有了。

如何使用

<ac:Form 
    VerticalAlignment="Top"
    DataContext="{Binding Base_User2}"
    Margin="2">
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='UserName'}" Path="UserName" ControlType="TextBox"/>
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='Password'}" Path="Password" ControlType="PasswordBox"/>
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='Sex'}" Path="Sex" ItemsSource="SexList" ControlType="ComboBox"/>
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='Birthday'}" Path="Birthday" ControlType="DatePicker"/>
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='DepartmentId'}" Path="DepartmentId" ItemsSource="Departments" ControlType="TreeSelect"/>
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='RoleIdList'}" Path="RoleIdList" ItemsSource="RolesList" ControlType="MultiComboBox"/>
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='SelectedDuty'}" Path="SelectedDuty" ItemsSource="Duties" ControlType="ComboBox"/>
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='Email'}" Path="Email" ControlType="TextBox"/>
    <ac:FormCodeItem Header="{Binding .,Converter={StaticResource DisplayNameConverter},ConverterParameter='PhoneNumber'}" Path="PhoneNumber" ControlType="TextBox"/>
    <ac:FormCodeItem Header="提交" Path="SubmitCommand" ControlType="Submit"/>
</ac:Form>

是不是比FormItem用起来更方便简洁了。实现的效果和Form是一样的

最后老规矩,上源码地址,在Controls下的Form文件夹中。

https://gitee.com/akwkevin/AI-wpf-controls

posted @ 2022-06-18 09:40  竹天笑  阅读(381)  评论(0编辑  收藏  举报