This is a migrated thread and some comments may be shown as answers.

Excel-like filtering pin position

7 Answers 91 Views
GridView
This is a migrated thread and some comments may be shown as answers.
konrad
Top achievements
Rank 1
konrad asked on 09 Jan 2015, 03:15 PM
Hi,

Is it possible to somehow change the position of the pin button (that open Excel-like filtering context menu), so it will be placed under the column header text?
Check image: http://imgur.com/5WZu5UU

7 Answers, 1 is accepted

Sort by
0
Hristo
Telerik team
answered on 14 Jan 2015, 01:27 PM
Hi Dominik,

Thank you for writing.

Yes, it is possible to create a layout of GridHeaderCellElement with a filtering button similar to the one shown in your picture. To reach this visual appearance you would need to create a custom GridHeaderCellElement and override the logic for the setting the position of the StackLayout element containing the FilterButton. More information about the layout logic of Telerik Presentation Framework can be found here.

Please check the code snippet below with my sample implementation:
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
          
        this.radGridView1.BestFitColumns(BestFitColumnMode.AllCells);
        this.radGridView1.EnableFiltering = true;
        this.radGridView1.MasterTemplate.ShowHeaderCellButtons = true;
        this.radGridView1.MasterTemplate.ShowFilteringRow = false;
    }
  
    private void radGridView1_CreateCell(object sender, GridViewCreateCellEventArgs e)
    {
        if (e.CellType == typeof(GridHeaderCellElement))
        {
            e.CellElement = new CustomGridHeaderCellElement(e.Column, e.Row);
        }
    }
  
    private void Form1_Load(object sender, EventArgs e)
    {
        this.productsTableAdapter.Fill(this.nwindDataSet.Products);
  
        radGridView1.MasterView.TableHeaderRow.Height = 100;
    }
}


public class CustomGridHeaderCellElement : GridHeaderCellElement
{
    public CustomGridHeaderCellElement(GridViewColumn column, GridRowElement row)
        : base(column, row)
    {
    }
 
    protected override Type ThemeEffectiveType
    {
        get
        {
            return typeof(GridHeaderCellElement);
        }
    }
 
    private bool IsTextRightAligned()
    {
        if (
            ((this.TextAlignment == System.Drawing.ContentAlignment.MiddleRight ||
            this.TextAlignment == System.Drawing.ContentAlignment.TopRight ||
            this.TextAlignment == System.Drawing.ContentAlignment.BottomRight) && !this.RightToLeft)
            ||
            ((this.TextAlignment == System.Drawing.ContentAlignment.MiddleLeft ||
            this.TextAlignment == System.Drawing.ContentAlignment.TopLeft ||
            this.TextAlignment == System.Drawing.ContentAlignment.BottomLeft) && this.RightToLeft))
        {
            return true;
        }
 
        return false;
    }
 
    protected override SizeF ArrangeOverride(SizeF finalSize)
    {
        this.ArrowPosition = SetArrowPosition();
 
        RectangleF clientRect = GetClientRectangle(finalSize);
        float cellWidth = clientRect.Width;
 
        //arrange the text according to filter button (stack layout)
        if (this.StackLayout.Visibility == ElementVisibility.Visible && this.FilterButton.Visibility == ElementVisibility.Visible)
        {
            float diff = finalSize.Width - this.StackLayout.DesiredSize.Width - this.Layout.DesiredSize.Width;
 
            if (diff > 0 && !this.IsTextRightAligned())
            {
                diff = this.StackLayout.DesiredSize.Width;
            }
            else
            {
                diff = 0;
            }
 
            clientRect.Width -= this.StackLayout.DesiredSize.Width - diff;
 
            if (this.RightToLeft)
            {
                clientRect.X += this.StackLayout.DesiredSize.Width - diff;
            }
        }
 
        if (this.ArrowPosition != ArrowPositionEnum.Top && this.ArrowPosition != ArrowPositionEnum.Bottom)
        {
            clientRect.Width -= 2 * this.Arrow.DesiredSize.Width + 2;
 
            if (this.RightToLeft)
            {
                clientRect.X += 2 * this.Arrow.DesiredSize.Width + 2;
            }
        }
 
        this.Layout.Arrange(clientRect);
        foreach (RadElement element in this.Children)
        {
            if (element.Visibility == ElementVisibility.Collapsed)
            {
                continue;
            }
            if (element == this.Arrow)
            {
                if (!this.ViewTemplate.EnableSorting)
                {
                    element.Visibility = ElementVisibility.Hidden;
                    continue;
                }
 
                //prevent an arrow from going into another column when the width is very small
                if (finalSize.Width - 2 * this.Arrow.DesiredSize.Width > 0 && 2 * this.Arrow.DesiredSize.Width < finalSize.Width)
                {
                    if (this.SortOrder != null && this.SortOrder != RadSortOrder.None && this.ColumnInfo.SortOrder != RadSortOrder.None)
                    {
                        element.Visibility = ElementVisibility.Visible;
                    }
 
                    ArrangeArrow(finalSize, element);
                }
                else
                {
                    element.Visibility = ElementVisibility.Hidden;
                }
            }
            else if (element == this.StackLayout)
            {
                if (this.RightToLeft)
                {
                    this.StackLayout.Arrange(new RectangleF(
                        0,
                        (finalSize.Height - this.StackLayout.DesiredSize.Height) / 2,
                        this.StackLayout.DesiredSize.Width, this.StackLayout.DesiredSize.Height
                        ));
                }
                else
                {
                    this.StackLayout.Arrange(new RectangleF(
                        finalSize.Width / 2 - this.StackLayout.DesiredSize.Width / 2,
                        finalSize.Height / 2 + this.StackLayout.DesiredSize.Height / 2,
                        this.StackLayout.DesiredSize.Width, this.StackLayout.DesiredSize.Height
                        ));
                }
            }
            else
            {
                this.ArrangeElement(element, finalSize, clientRect);
            }
        }
 
 
        return finalSize;
    }
 
}

I am also sending you a screenshot showing how the grid looks on my side.

I hope this information is useful. Should you have further questions please do not hesitate to write back.

Regards,
Hristo
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
konrad
Top achievements
Rank 1
answered on 20 Jan 2015, 08:20 AM
Thank you for the solution. It works well.

However, I have another question.
How in the filter row change the standard PopUp to Excel-like PopUp? 
Check image: FilterPopUp
0
Hristo
Telerik team
answered on 22 Jan 2015, 03:37 PM
Hi Dominik,

Thank you for writing back.

You could reach this type of drop down menu by subscribing to the ContextMenuOpening event and if the provider is GridFilterCellElement then create a new excel-like filter pop up. Please find my code example below:
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
 
        this.radGridView1.BestFitColumns(BestFitColumnMode.AllCells);
        this.radGridView1.EnableFiltering = true;
        this.radGridView1.MasterTemplate.ShowHeaderCellButtons = true;
        this.radGridView1.MasterTemplate.ShowFilteringRow = true;
    }
 
    private void radGridView1_CreateCell(object sender, GridViewCreateCellEventArgs e)
    {
        if (e.CellType == typeof(GridHeaderCellElement))
        {
            e.CellElement = new CustomGridHeaderCellElement(e.Column, e.Row);
        }
    }
 
    private void Form1_Load(object sender, EventArgs e)
    {
        this.productsTableAdapter.Fill(this.nwindDataSet.Products);
        radGridView1.MasterView.TableHeaderRow.Height = 50;
    }
 
    string columnName = string.Empty;
    private void radGridView1_ContextMenuOpening(object sender, ContextMenuOpeningEventArgs e)
    {
        GridFilterCellElement menuProvider = e.ContextMenuProvider as GridFilterCellElement;
        if (menuProvider != null)
        {
            e.Cancel = true;
            columnName = menuProvider.ColumnInfo.Name;
 
            IGridFilterPopup filterPopup = CreateFilterPopup(menuProvider);
            FieldInfo fi = this.radGridView1.TableElement.GetType().GetField("gridFilterPopup", BindingFlags.NonPublic | BindingFlags.Instance);
            fi.SetValue(this.radGridView1.TableElement, filterPopup);
            filterPopup.FilterConfirmed += filterPopup_FilterConfirmed;
            filterPopup.Show(Cursor.Position);
        }
    }
 
    private void filterPopup_FilterConfirmed(object sender, EventArgs e)
    {
        IGridFilterPopup filterPopup = (IGridFilterPopup)sender;
        filterPopup.FilterConfirmed -= filterPopup_FilterConfirmed;
 
 
        if (this.radGridView1.FilterDescriptors.Contains(columnName) && columnName != string.Empty)
        {
            this.radGridView1.MasterTemplate.EventDispatcher.SuspendEvent(EventDispatcher.FilterChangingEvent);
            this.radGridView1.MasterTemplate.EventDispatcher.SuspendEvent(EventDispatcher.FilterChangedEvent);
            this.radGridView1.FilterDescriptors.Remove(columnName);
            this.radGridView1.MasterTemplate.EventDispatcher.ResumeEvent(EventDispatcher.FilterChangingEvent);
            this.radGridView1.MasterTemplate.EventDispatcher.ResumeEvent(EventDispatcher.FilterChangedEvent);
        }
        if (filterPopup.FilterDescriptor != null)
        {
            filterPopup.FilterDescriptor.IsFilterEditor = true;
            this.radGridView1.FilterDescriptors.Add(filterPopup.FilterDescriptor);
            this.Focus();
        }
    }
 
    private IGridFilterPopup CreateFilterPopup(GridFilterCellElement cell)
    {
        BaseFilterPopup filterPopup = null;
 
        if (cell.ColumnInfo is GridViewDateTimeColumn)
        {
            filterPopup = new RadDateFilterPopup((GridViewDataColumn)cell.ColumnInfo);
        }
        else
        {
            filterPopup = new RadListFilterPopup((GridViewDataColumn)cell.ColumnInfo);
        }
 
        filterPopup.SetTheme(this.radGridView1.ThemeName);
        filterPopup.RightToLeft = cell.RightToLeft ? System.Windows.Forms.RightToLeft.Yes : System.Windows.Forms.RightToLeft.No;
        filterPopup.HorizontalPopupAlignment = cell.RightToLeft ? HorizontalPopupAlignment.RightToRight :
                                                                  HorizontalPopupAlignment.LeftToLeft;
 
        return filterPopup;
    }
}

I am also sending you a .gif file showing how the grid behaves on my side.

I hope this helps. Should you have further questions please do not hesitate to write back.

Regards,
Hristo
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
konrad
Top achievements
Rank 1
answered on 23 Jan 2015, 07:55 AM
Hi, 

Thanks for the very professional answer.
However, there is a problem with DateTime columns.

In line:
fi.SetValue(_DG.TableElement, filterPopup);

Error:
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: Object of type 'Telerik.WinControls.UI.RadDateFilterPopup' cannot be converted to type 'Telerik.WinControls.UI.IGridFilterPopupInteraction'.
0
Accepted
Hristo
Telerik team
answered on 27 Jan 2015, 01:31 PM
Hello,

Thank you for writing back.

This exception is caused by the fact that the filter popup element of a GridViewDateTimeColumn does not implement the IGridFilterPopupInteraction interface which is actually the type of the field we are trying to set. With the following cast your application should not throw this exception anymore. Please see below:
FieldInfo fi = this.radGridView1.TableElement.GetType().GetField("gridFilterPopup", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(this.radGridView1.TableElement, filterPopup as IGridFilterPopupInteraction);

I hope this helps. Should you have further questions please do not hesitate to write back.

Regards,
Hristo Merdjanov
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
konrad
Top achievements
Rank 1
answered on 13 May 2015, 12:02 PM
Thank you for the solution. It works well.
0
konrad
Top achievements
Rank 1
answered on 13 May 2015, 12:02 PM
Thank you for the solution. It works well.
Tags
GridView
Asked by
konrad
Top achievements
Rank 1
Answers by
Hristo
Telerik team
konrad
Top achievements
Rank 1
Share this question
or