Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
137 views
in Technique[技术] by (71.8m points)

c# - Improving Winforms performance with large number of controls

Are there any ways to improve performance when constructing several forms with large numbers of controls (500+)?

Our controls are laid out in a label + 6 text box per row configuration, as shown below:

image

We have used the following containers to structure our controls:

  • DevExpress' XtraLayoutControl
  • Panels around each row and moving manually
  • Common table control

We can't use a grid as the text boxes have to be hidden on a case-by-case basis and our forms have to look fairly close to the printouts. Also, each row has it's own data type, so we need to add validation and editors for each.

The table control is the most performant, where each form takes around 2 seconds to load.

As each of these will represent a document in our software and we allow users to open multiple documents at once, we are trying to find a way to improve the performance.

One suggestion was to cache the actual form and have a state object that stores the data. However, we allow the user to see more than one document at once.

Another suggestion was to load the document in parts and show each part as it becomes loaded. This isn't ideal as we are known for having a document that looks almost exactly like the printout.

Are there any other strategies available, or should we just bight the bullet at tell our customers that this program will be slower than it's VB6 predecessor?

An example of the form design we're redeveloping is here: Link

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Complex datatype handling and stuff is to you, this is a 5 minute before-lunch sample to show how much winforms sucks and how much WPF rules:

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>

I see that you have several other requirements here, such as hiding texboxes and stuff. It doesn't matter if these rows are a different data type, you just need to do a ViewModel (which in this case would be my public class Item, which hold the data you want to show in the screen, and let the user be able to interact with.

For example, you could replace the List<string> inside the Item class with something more complex, and add some properties like public bool IsVisible {get;set;} and so on.

I strongly suggest you take a look at WPF (at least for this screen in particular).

Copy and paste my code in a new -> WPF project and you can see the results for yourself.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...