Need a very customized large Winforms grid

I am going to develop an application for a Windows PC (it can be WinForms or WPF), and my main problem is the user interface problem, which I will have to solve.

Basically, I need to have a grid about 50x50 in size, for which I need to get input from the user. These are 2500 fields. In reality, most will be left blank, about 10% will be filled by the user. Each field can be empty or have a number from 1 to 4. I want a simple input - perhaps a drop-down field (since it makes no sense to insert all 2500 fields when using the keyboard, I want the user to fill in the values ​​with the mouse).

I thought about drop-down boxes or even labels that change value when clicking on them, but the problem is that (from the tests performed) adding 2500 of any type of control will make the interface terribly slow. I tried using tablelayoutpanel in a WinForms application with suspend / resumeupdate functions as well as double buffering, and this helps a bit, but it is still very slow. I don't want to go the DataGridView path, because I need VERY customizable headers, and I need the user interface to automatically update some percentages when the user changes the values ​​in the fields. But I will not mind if this is the only option.

I heard that WPF could be better, since you can have many controls, and each of them does not accept its own window handle, and there is virtualization (not sure how difficult it is to implement).

I am open to suggestions. I know someone will suggest breaking the grid, what can I do. In any case, I would like to find out the most effective method for a large grid with a lot of controls in a Windows application, as if I were going to develop this without breaking the grid.

I am using VS 2013, developing in C #, .NET 4.0.

Thanks!

+2
source share
4 answers

@Kerry, winforms : " winforms, , winforms". - , - .

, WPF 10 < > 20 # 50 XAML

enter image description here

  • WPF ( I5 ). ( UniformGrid, ), , , - winforms.
  • ComboBox 1-4 .
  • ( "" ). , , , .
  • Touch-Ready - . -, winforms . Excel , .
  • , .
  • ListBox, , SelectedItem, , ListBox ( - ).
  • , ViewModel , ItemsControls, WPF . # , . DataBinding.

:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate x:Key="MarkerTemplate">
            <Border BorderBrush="Gray" BorderThickness="1" Margin="1" Background="Gainsboro">
                <Grid Width="50" Height="30">
                    <TextBlock Text="{Binding}" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                </Grid>
            </Border>
        </DataTemplate>

        <Style TargetType="ListBoxItem">
            <Setter Property="Padding" Value="0"/>
        </Style>
    </Window.Resources>

    <DockPanel>
        <ListBox ItemsSource="{Binding Items}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Gray" BorderThickness="1">
                    <Grid Width="50" Height="30">
                        <TextBlock Text="{Binding Value}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                        <ComboBox x:Name="ComboBox" SelectedItem="{Binding Value}" 
                                  IsDropDownOpen="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
                                  Visibility="Collapsed">
                            <sys:Int32>1</sys:Int32>
                            <sys:Int32>2</sys:Int32>
                            <sys:Int32>3</sys:Int32>
                            <sys:Int32>4</sys:Int32>
                        </ComboBox>
                    </Grid>
                    </Border>
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="True">
                            <Setter TargetName="ComboBox" Property="Visibility" Value="Visible"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ListBox.ItemTemplate>

            <ListBox.Template>
                <ControlTemplate TargetType="ListBox">
                    <ScrollViewer CanContentScroll="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
                        <DockPanel>
                            <ItemsControl DockPanel.Dock="Top" ItemsSource="{Binding ColumnMarkers}"
                                ItemTemplate="{StaticResource MarkerTemplate}">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <VirtualizingStackPanel Orientation="Horizontal"/>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                            </ItemsControl>

                            <ItemsControl DockPanel.Dock="Left" ItemsSource="{Binding RowMarkers}"
                                          ItemTemplate="{StaticResource MarkerTemplate}">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <VirtualizingStackPanel Orientation="Vertical"/>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                            </ItemsControl>

                            <UniformGrid Rows="50" Columns="50" IsItemsHost="True"/>
                        </DockPanel>
                    </ScrollViewer>
                </ControlTemplate>
            </ListBox.Template>
        </ListBox>
    </DockPanel>
</Window>

:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;

namespace WpfApplication3
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new ViewModel();
        }
    }
}

ViewModel:

public class ViewModel
{
    public List<string> RowMarkers { get; set; }

    public List<string> ColumnMarkers { get; set; }

    public ObservableCollection<Item> Items { get; set; }

    public ViewModel()
    {
        RowMarkers = Enumerable.Range(1, 50).Select(x => x.ToString()).ToList();
        ColumnMarkers = new[] { " " }.Concat(Enumerable.Range(1, 50).Select(x => x.ToString())).ToList();

        var list = new List<Item>();

        for (int i = 0; i < 50; i++)
        {
            for (int j = 0; j < 50; j++)
            {
                list.Add(new Item());
            }
        }

        Items = new ObservableCollection<Item>(list);
    }
}

:

public class Item
{
    public int? Value { get; set; }
}
  • , , Row Column Item, , / . LINQ :

    var values = Items.Where(x => Value != null);
    

    Item item.Row Item.Column .

  • winforms. . - winforms . , winforms, WPF 10% , , . winforms - , . , UI. Microsoft WPF .

  • WPF Rocks. File -> New Project -> WPF Application .

  • , .

: WPF Windows 8 , Windows 7 ( Windows 8 Aero ).

, Windows 7 . , , . . XAML ( Style ControlTemplate s) Windows 7 "".

+4

, , , , , , . , WPF ( IF, ) , , , , , ' ".

( ), . .., . ( ), , -, ToolBox, . , . [x, y], .

public class ValuesPanel : Panel
{
    public int this[int x, int y] { get { return cells[x, y]; } set { cells[x, y] = value; } }
    private int[,] cells = new int[50, 50];
    const int cell_width = 15, cell_height = 15;
    private int x, y, scroll_x, scroll_y;

    public ValuesPanel()
    {
        SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);
        AutoScrollMinSize = new Size(50 * cell_width, 50 * cell_height);
        BorderStyle = BorderStyle.Fixed3D;
        Cursor = Cursors.Hand;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.FillRectangle(Brushes.DeepSkyBlue, x * cell_width - scroll_x, y * cell_height - scroll_y, cell_width, cell_height);
        for (int j = 0; j < 50; j++)
            for (int i = 0; i < 50; i++)
            {
                int xx = i * cell_width - scroll_x, yy = j * cell_height - scroll_y;
                e.Graphics.DrawString(cells[i, j].ToString(), Font, new SolidBrush(ForeColor), new PointF(3 + xx, 1 + yy));
                e.Graphics.DrawLine(Pens.Gray, xx, yy, xx + cell_width - 2, yy);
                e.Graphics.DrawLine(Pens.Gray, xx, yy + cell_height - 2, xx, yy);
                e.Graphics.DrawLine(Pens.White, xx + 1, yy + cell_height - 1, xx + cell_width - 1, yy + cell_height - 1);
                e.Graphics.DrawLine(Pens.White, xx + cell_width - 1, yy + 1, xx + cell_width - 1, yy + cell_height - 1);
            }
    }

    protected override void OnScroll(ScrollEventArgs se)
    {
        Invalidate();
        base.OnScroll(se);
        scroll_x = HorizontalScroll.Value;
        scroll_y = VerticalScroll.Value;
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        x = Math.Min(49, (e.Location.X + scroll_x) / cell_width);
        y = Math.Min(49, (e.Location.Y + scroll_y) / cell_height);
        Invalidate();
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (e.Button == MouseButtons.Left)
            cells[x, y] = (cells[x, y] % 4) + 1;
        else if (e.Button == MouseButtons.Right)
            cells[x, y] = cells[x, y] < 2 ? 4 : cells[x, y] - 1;
    }
}

WPF, , WinForms "". !;)

+4

.

, "" Visual Studio. , (, , , ..). , datagridview, , .

datagridview.

"", .

Datagridview . 15-20 , .

combobox, .

.

50x50, , , , . , . .

0

, , StackOverflow. WinForms , , .

, iGrid WinForms grid :

private iGDropDownList myCombo = new iGDropDownList();

private void Form1_Load(object sender, EventArgs e)
{
    myCombo.Items.Add(1);
    myCombo.Items.Add(2);
    myCombo.Items.Add(3);
    myCombo.Items.Add(4);

    iGrid1.DefaultCol.CellStyle.DropDownControl = myCombo;

    iGrid1.Cols.Count = 50;
    iGrid1.Rows.Count = 50;
}

:

WinForms grid socket cell

, , ShowControlsInAllCells false.

iGrid , . iGrid combobox, , . , iGrid , 50 500'000 - .

You can add to this that iGrid is still being developed and maintained even in 2017!

0
source

Source: https://habr.com/ru/post/1527593/


All Articles