使用大量控件提高Winforms的性能

时间:2013-01-28 15:49:55

标签: c# .net winforms

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

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

Image http://s7.postimage.org/cdhay2c23/test.png

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

  • DevExpress'XtraLayoutControl
  • 每行周围的面板并手动移动
  • 公用表格控件

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

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

由于其中每个都代表我们软件中的文档,并且我们允许用户一次打开多个文档,我们正在努力寻找提高性能的方法。

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

另一个建议是将文档分批加载并在加载时显示每个部分。这并不理想,因为我们知道文档几乎与打印输出完全一样。

是否有其他可用的策略,或者我们应该告诉客户这个程序会比VB6前辈慢吗?

我们重新开发的表单设计示例如下:Link

2 个答案:

答案 0 :(得分:3)

复杂的数据类型处理和东西是给你的,这是一个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 (在这种情况下将是我的public class Item,其中包含您想要的数据在屏幕上显示,让用户能够与之互动。

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

我强烈建议你看看WPF(至少在这个屏幕上)。

将我的代码复制并粘贴到新的 - &gt; WPF项目,您可以自己查看结果。

答案 1 :(得分:2)

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

我不明白为什么这会排除使用DataGridView。通过将DataGridViewCell属性设置为ReadOnly,可以将特定true设为只读。然后,您可以使用DataGridView.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;
    }
}