2

在构建具有大量控件(500+)的多个表单时,有什么方法可以提高性能?

我们的控件布局在一个标签+每行6个文本框的配置中,如下所示:

图片

我们使用以下容器来构建我们的控件:

  • DevExpress 的 XtraLayoutControl
  • 每行周围的面板并手动移动
  • 普通表控件

我们不能使用网格,因为必须根据具体情况隐藏文本框,并且我们的表单必须看起来非常接近打印输出。此外,每一行都有自己的数据类型,因此我们需要为每一行添加验证和编辑器。

表格控件是性能最高的,每个表单加载大约需要 2 秒。

由于每一个都将代表我们软件中的一个文档,并且我们允许用户一次打开多个文档,因此我们正试图找到一种提高性能的方法。

一个建议是缓存实际表单并拥有一个存储数据的状态对象。但是,我们允许用户一次查看多个文档。

另一个建议是分部分加载文档并在加载时显示每个部分。这并不理想,因为我们以拥有与打印输出几乎一模一样的文档而闻名。

是否有任何其他可用的策略,或者我们是否应该硬着头皮告诉我们的客户该程序将比它的 VB6 前身慢?

我们正在重新开发的表单设计示例如下:链接

4

2 回答 2

4

复杂的数据类型处理和东西是给你的,这是午餐前 5 分钟的示例,显示了多少 winforms 很糟糕以及多少 WPF 规则:

namespace WpfApplication5
{

public partial class MainWindow : Window
{
    private List<Item> _items;
    public List<Item> Items
    {
        get { return _items ?? (_items = new List<Item>()); }
    }

    public MainWindow()
    {
        InitializeComponent();

        Items.Add(new Item() {Description = "Base metal Thickness"});

        for (var i = 32; i > 0; i--)
        {
            Items.Add(new Item() {Description = "Metal Specification " + i.ToString()});
        }

        Items.Add(new Item() { Description = "Base metal specification" });

        DataContext = this;
    }
}

public class Item: INotifyPropertyChanged
{
    private List<string> _values;
    public List<string> Values
    {
        get { return _values ?? (_values = new List<string>()); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public string Description { get; set; }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) 
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

    public Item()
    {
        Values.Add("Value1");
        Values.Add("Value2");
        Values.Add("Value3");
        Values.Add("Value4");
        Values.Add("Value5");
        Values.Add("Value6");
    }
}
}

XAML:

<Window x:Class="WpfApplication5.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <ItemsControl ItemsSource="{Binding Items}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Description}" Width="130"/>
                    <ItemsControl ItemsSource="{Binding Values}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <TextBox Text="{Binding Path=.}" Margin="2" Width="90"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

我看到您在这里还有其他几个要求,例如隐藏 texbox 和其他东西。如果这些行是不同的数据类型并不重要,你只需要做一个ViewModel(在这种情况下是 my public class Item,它保存你想在屏幕上显示的数据,并让用户能够交互和。

例如,您可以将类List<string>内部替换为Item更复杂的内容,并添加一些诸如此类public bool IsVisible {get;set;}的属性。

我强烈建议你看看 WPF(至少对于这个屏幕来说)。

将我的代码复制并粘贴到一个新的 -> WPF 项目中,您可以自己查看结果。

于 2013-01-28T16:28:26.770 回答
2

We can't use a grid as the text boxes have to be hidden on a case-by-case basis.

我不明白为什么这会阻止使用DataGridView. 通过将属性设置为 ,可以将特定DataGridViewCell设置为只读。然后,您可以使用该事件来隐藏只读单元格的值。如果我没记错的话,代码将类似于:ReadOnlytrueDataGridView.CellFormatting

private void grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    DataGridView grid = (DataGridView)sender;
    if (grid[e.ColumnIndex, e.RowIndex].ReadOnly)
    {
        e.Value = string.Empty;
        e.FormattingApplied = true;
    }
}
于 2013-01-28T16:11:38.573 回答