블로그 이미지
* Microsoft MVP - Windows Development 2014 ~ 2019 5ring * LINE : kaki104 * facebook : https://www.facebook.com/kaki104 https://www.facebook.com/groups/w10app/ kaki104

카테고리

List All (569)
Xamarin Forms (4)
Bot Framework (19)
Azure (9)
Windows 10 (44)
WPF (3)
Facebook News & Tips (158)
Windows App(Universa.. (90)
Windows 8&8.1 (113)
Windows Phone 8 (42)
Silverlight (37)
HTML5 & MVC4 (16)
Portable Class Library (2)
Uncategorised Tips a.. (3)
Kinect for Windows (2)
ETC (12)
kaki104 Scrap (4)
App News (11)
Total530,056
Today0
Yesterday19

C1FlexGrid에 Custom MergeManager를 만들어서 사용하는 방법에 대한 예제가 모두 grid[r,c]에서 값을 가지고 와서 비교하도록 되어 있는데, 이 부분이 성능에 많은 영향을 줍니다. 


그래서, CollectionView에서 데이터를 직접 찾아서 비교하는 방법으로 성능을 50% 이상 올릴 수 있는 방법을 셈플로 만들어 보았습니다.


위의 성능 프로파일러만 보더라도 확연히 차이가 나는 것을 알 수 있습니다.


MainWindow.xaml


<Window x:Class="FlexGridMergeManagerSampleForWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:FlexGridMergeManagerSampleForWPF"
        xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <Button Content="Using grid[r,c]" Click="ButtonBase_OnClick" />
            <Button Content="Using CollectionView" Click="ButtonBase_OnClick" />
        </StackPanel>
        <c1:C1FlexGrid x:Name="FlexGrid" Grid.Row="1"
                       HeadersVisibility="All"
                       AutoGenerateColumns="False"
                       AllowMerging="All"
                       GridLinesVisibility="All"
                       GridLinesBrush="LightGray"
                       FrozenLinesBrush="#FF2A4C80"
                       ColumnHeaderBackground="#FFDBE1E9"
                       RowHeaderBackground="#FFDBE1E9"
                       TopLeftCellBackground="#FFBAD2F5"
                       IsReadOnly="True"
                       AllowResizing="Both"
                       AllowSorting="True"
                       ShowMarquee="True"
                       ClipboardCopyMode="ExcludeHeader">
            <c1:C1FlexGrid.Columns>
                <c1:Column Binding="{Binding OrderID}" AllowMerging="False" />
                <c1:Column Binding="{Binding ProductID}" AllowMerging="True" />
                <c1:Column Binding="{Binding ProductName}" AllowMerging="True"/>
                <c1:Column Binding="{Binding UnitPrice}" AllowMerging="True" />
                <c1:Column Binding="{Binding Quantity}" AllowMerging="True" />
                <c1:Column Binding="{Binding Discount}" AllowMerging="True" />
                <c1:Column Binding="{Binding ExtendedPrice}" AllowMerging="True" />
            </c1:C1FlexGrid.Columns>
        </c1:C1FlexGrid>
    </Grid>
</Window>



MainWindow.xaml.cs


using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using C1.WPF.FlexGrid;

namespace FlexGridMergeManagerSampleForWPF
{
    /// <summary>
    ///     Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private const string CASE1 = "Using grid[r,c]";
        private const string CASE2 = "Using CollectionView";

        public MainWindow()
        {
            InitializeComponent();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            var button = (Button) sender;
            switch (button.Content.ToString())
            {
                case CASE1:
                    BindGrid(CASE1);
                    break;
                case CASE2:
                    BindGrid(CASE2);
                    break;
            }
        }

        private void BindGrid(string type)
        {
            FlexGrid.MergeManager = new SampleMergeManager(type);

            var allText = File.ReadAllText("sample.csv");
            if (string.IsNullOrEmpty(allText)) return;
            var lines = allText.Split('\n');

            var items = (from line in lines.Skip(1)
                where string.IsNullOrEmpty(line) == false
                let columns = line.Split(',')
                select new SampleModel
                {
                    OrderID = Convert.ToInt32(columns[0]),
                    ProductID = Convert.ToInt32(columns[1]),
                    ProductName = columns[2],
                    UnitPrice = Convert.ToDouble(columns[3]),
                    Quantity = Convert.ToInt32(columns[4]),
                    Discount = Convert.ToDouble(columns[5]),
                    ExtendedPrice = Convert.ToDouble(columns[6].Replace("\r", ""))
                }).ToList();

            // bind grids to ListCollectionView
            FlexGrid.ItemsSource = items;
        }

        private class SampleMergeManager : IMergeManager
        {
            private static long _count;
            private readonly string _getDataType;

            public SampleMergeManager(string type)
            {
                _getDataType = type;
            }

            public CellRange GetMergedRange(C1FlexGrid grid, CellType cellType, CellRange rng)
            {
                if (cellType != CellType.Cell) return rng;
                var col = grid.Columns[rng.Column];
                if (col.AllowMerging == false) return rng;

                for (var i = rng.Row; i < grid.Rows.Count - 1; i++)
                {
                    if (CompareNext(grid, i, rng.Column))
                        break;
                    rng.Row2 = i + 1;
                }

                for (var i = rng.Row; i > 0; i--)
                {
                    if (ComparePrev(grid, i, rng.Column))
                        break;
                    rng.Row = i - 1;
                }

                _count++;
                Debug.WriteLine($"count : {_count}");
                return rng;
            }

            private bool CompareNext(C1FlexGrid grid, int r, int c)
            {
                if (_getDataType == CASE1)
                    return grid[r, c]?.ToString() != grid[r + 1, c]?.ToString();

                var col = grid.Columns[c];
                if (!(grid.CollectionView is ListCollectionView collection)) return false;
                var item1 = collection.GetItemAt(r);
                var item2 = collection.GetItemAt(r + 1);

                var property = item1.GetType().GetProperty(col.Binding.Path.Path);
                if (property == null) return false;
                var val1 = property.GetValue(item1);
                var val2 = property.GetValue(item2);

                return val1?.ToString() != val2?.ToString();
            }

            private bool ComparePrev(C1FlexGrid grid, int r, int c)
            {
                if (_getDataType == CASE1)
                    return grid[r, c]?.ToString() != grid[r - 1, c]?.ToString();

                var col = grid.Columns[c];
                if (!(grid.CollectionView is ListCollectionView collection)) return false;
                var item1 = collection.GetItemAt(r);
                var item2 = collection.GetItemAt(r - 1);

                var property = item1.GetType().GetProperty(col.Binding.Path.Path);
                if (property == null) return false;
                var val1 = property.GetValue(item1);
                var val2 = property.GetValue(item2);

                return val1?.ToString() != val2?.ToString();
            }

        }
    }
}


소스

https://github.com/kaki104/BasicSamples/tree/master/FlexGridMergeManagerSampleForWPF


'WPF' 카테고리의 다른 글

FlexGrid MergerManager 성능 개선 셈플 및 그래프  (0) 2018.12.20
GrapeCity WPF Edition (C1) tip  (0) 2018.12.19
.NetFrame 4.5 working tip  (0) 2013.06.12
Posted by MVP kaki104