Beispiel #1
0
        /// <summary>
        /// Рендеринг компонента
        /// </summary>
        /// <param name="drawingContext">контекст рисования</param>
        protected override void OnRender(DrawingContext drawingContext)
        {
            #region Алгоритм подготовки к рисованию
            base.OnRender(drawingContext);
            //Текущая фактическая высота области рисования
            double currentHeight = this.RenderSize.Height - this.hScrollBar.RenderSize.Height;
            //Текущая фактическая ширина области рисования
            double currentWidth = this.RenderSize.Width - this.vScrollBar.RenderSize.Width;
            //Область рисования (вне этой области рисовать нельзя)
            Size clipSize = new Size(currentWidth, currentHeight);
            //ограничиваем
            drawingContext.PushClip(new RectangleGeometry(new Rect(new Point(0, 0), clipSize)));
            //очищаем фон
            drawingContext.DrawRectangle(this.ЦветФона, null, new Rect(new Point(0, 0), clipSize));
            //Проверка на кол-во строк
            if (this.СписокСтрок.Count <= 0)
            {
                return;
            }
            //текущий индекс рисуемой строки
            int индекс = this.ИндексПервойВидимойСтроки;
            //текущая точка рисования на канвасе компонента
            Point текущаяТочкаРендеринга = new Point(0, 0);
            //учёт горизонтального скроллинга (если ползунок передвинут) (в случае когда не помещается полностью элемент)
            текущаяТочкаРендеринга.X = -this.hScrollBar.Value;
            //обнуляем вертикальный скролбар (нечего отображать)
            this.hScrollBar.Maximum = 0;
            //очистка Списка областей (прямоугольников), в которых отрисованы видымые элементы списка SourceData
            this.СписокПрямоугольныхОбластейВидимыхСтрок.Clear();
            #endregion
            #region Цикл отрисовки видимых блоков (элементов) - пока они видны на экране (канвасе компонента)
            while (текущаяТочкаРендеринга.Y < currentHeight)
            {
                //Проверка индексов на допустимость
                if (индекс < 0)
                {
                    return;
                }
                //Обработка ситуации превышения текущего индекса над общим кол-вом строк
                if (индекс >= this.СписокСтрок.Count)
                {
                    break;
                }

                //преобразоваем элемент пользовательского типа в универсальный шаблон отображения
                BlockBase блокТекущейРисуемойСтроки = this.ConvertToBlockTemplate(this.СписокСтрок[индекс], индекс);

                //рендерим шаблон
                DrawingVisual визуальныйБуферТекущейРисуемойСтроки = блокТекущейРисуемойСтроки.Render(текущаяТочкаРендеринга);
                //рисуем его на канвасе компонента
                drawingContext.DrawDrawing(визуальныйБуферТекущейРисуемойСтроки.Drawing);
                //область рисования текущего шаблона
                Rect прямоугольнаяОбластьТекущейРисуемойСтроки = new Rect(текущаяТочкаРендеринга, блокТекущейРисуемойСтроки.RenderSize);
                //добавляем его в список (пригодится для реализации клика по элементу)
                this.СписокПрямоугольныхОбластейВидимыхСтрок.Add(прямоугольнаяОбластьТекущейРисуемойСтроки);

                //выбираем самую длинную ширину (самы длинный элемент) (для реализации горизонтального скроллинга)
                double deltaWidth = блокТекущейРисуемойСтроки.RenderSize.Width - currentWidth;
                if (deltaWidth > 0)
                {
                    if (this.hScrollBar.Maximum <= deltaWidth)
                    {
                        this.hScrollBar.Maximum = deltaWidth; hScrollBar.IsEnabled = true;
                    }
                }

                //переходим вниз, на свободное место для рисования
                текущаяТочкаРендеринга.Y += блокТекущейРисуемойСтроки.RenderSize.Height;
                //переход к следующей строке
                индекс++;
            }
            #endregion
            #region Выделение активной строки - отрисовка курсора
            if ((ПозицияКурсора_Строка >= ИндексПервойВидимойСтроки) && (ПозицияКурсора_Строка < (ИндексПервойВидимойСтроки + СписокПрямоугольныхОбластейВидимыхСтрок.Count)))
            {
                //отрисовка курсора - по факту это прямоугольник :)))
                drawingContext.DrawRectangle
                (
                    this.Foreground /*цвет курсора*/, null,
                    new Rect
                    (
                        СписокПрямоугольныхОбластейВидимыхСтрок[ПозицияКурсора_Строка - ИндексПервойВидимойСтроки].TopRight /*Положение курсора*/,
                        new Size
                        (
                            ШиринаКурсора /*установка ширины курсора*/,
                            СписокПрямоугольныхОбластейВидимыхСтрок[ПозицияКурсора_Строка - ИндексПервойВидимойСтроки].Height            /*Установка высоты курсора*/
                        )
                    )
                );
            }
            #endregion
        }