Pure Server-Side Filtering with RadGridView and WCF RIA Services

Wednesday, March 24, 2010 by Rossen Hristov | Comments 25

PureServerSideFiltering

Those of you who are familiar with WCF RIA Services know that the DomainDataSource control provides a FilterDescriptors collection that enables you to filter data returned by the query on the server. We have been using this DomainDataSource feature in our “RIA Services with DomainDataSource” online example for almost an year now. In the example, we are listening for RadGridView’s Filtering event in order to intercept any filtering that is performed on the client and translate it to something that the DomainDataSource will understand, in this case a System.Windows.Data.FilterDescriptor being added or removed from its FilterDescriptors collection. Think of RadGridView.FilterDescriptors as client-side filtering and of DomainDataSource.FilterDescriptors as server-side filtering. We no longer need the client-side one.

With the introduction of the Custom Filtering Controls feature many new possibilities have opened. With these custom controls we no longer need to do any filtering on the client. I have prepared a very small project that demonstrates how to filter solely on the server by using a custom filtering control.

As I have already mentioned filtering on the server is done through the FilterDescriptors collection of the DomainDataSource control. This collection holds instances of type System.Windows.Data.FilterDescriptor. The FilterDescriptor has three important properties:

By adding filters, you can specify that only entities which meet the condition in the filter are loaded from the domain context. In case you are not familiar with these concepts you might find Brad Abrams’ blog interesting.

ServerSideFilteringDiagram

Now, our requirements are to create some kind of UI that will manipulate the DomainDataSource.FilterDescriptors collection. When it comes to collections, my first choice of course would be RadGridView. If you are not familiar with the Custom Filtering Controls concept I would strongly recommend getting acquainted with my step-by-step tutorial Custom Filtering with RadGridView for Silverlight and checking the online example out.

I have created a simple custom filtering control that contains a RadGridView and several buttons. This control is aware of the DomainDataSource instance, since it is operating on its FilterDescriptors collection. In fact, the RadGridView that is inside it is bound to this collection. In order to display filters that are relevant for the current column only, I have applied a filter to the grid. This filter is a Telerik.Windows.Data.FilterDescriptor and is used to filter the little grid inside the custom control. It should not be confused with the DomainDataSource.FilterDescriptors collection that RadGridView is actually bound to. These are the RIA filters.

Additionally, I have added several other features. For example, if you have specified a DataFormatString on your original column, the Value column inside the custom control will pick it up and format the filter values accordingly. Also, I have transferred the data type of the column that you are filtering to the Value column of the custom control. This will help the little RadGridView determine what kind of editor to show up when you begin edit, for example a date picker for DateTime columns. Finally, I have added four buttons – two of them can be used to add or remove filters and the other two will communicate the changes you have made to the server.

Here is the full source code of the DomainDataSourceFilteringControl.

The XAML:

<UserControl x:Class="PureServerSideFiltering.DomainDataSourceFilteringControl"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:telerikGrid="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView"

    xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls"

    Width="300">

    <Border x:Name="LayoutRoot"

            BorderThickness="1"

            BorderBrush="#FF8A929E"

            Padding="5"

            Background="#FFDFE2E5">

 

        <Grid>

            <Grid.RowDefinitions>

                <RowDefinition Height="Auto"/>

                <RowDefinition Height="150"/>

                <RowDefinition Height="Auto"/>

            </Grid.RowDefinitions>

 

            <StackPanel Grid.Row="0"

                        Margin="2"

                        Orientation="Horizontal"

                        HorizontalAlignment="Center">

                <telerik:RadButton Name="addFilterButton"

                                  Click="OnAddFilterButtonClick"

                                  Content="Add Filter"

                                  Margin="2"

                                  Width="96"/>

                <telerik:RadButton Name="removeFilterButton"

                                  Click="OnRemoveFilterButtonClick"

                                  Content="Remove Filter"

                                  Margin="2"

                                  Width="96"/>

            </StackPanel>

 

            <telerikGrid:RadGridView Name="filtersGrid"

                                    Grid.Row="1"

                                    Margin="2"

                                    ItemsSource="{Binding FilterDescriptors}"

                                    AddingNewDataItem="OnFilterGridAddingNewDataItem"

                                    ColumnWidth="*"

                                    ShowGroupPanel="False"

                                    AutoGenerateColumns="False"

                                    CanUserResizeColumns="False"

                                    CanUserReorderColumns="False"

                                    CanUserFreezeColumns="False"

                                    RowIndicatorVisibility="Collapsed"

                                    IsFilteringAllowed="False"

                                    CanUserSortColumns="False">

                <telerikGrid:RadGridView.Columns>

                    <telerikGrid:GridViewComboBoxColumn DataMemberBinding="{Binding Operator}"

                                                        UniqueName="Operator"/>

                    <telerikGrid:GridViewDataColumn Header="Value"

                                                    DataMemberBinding="{Binding Value.Value}"

                                                    UniqueName="Value"/>

                </telerikGrid:RadGridView.Columns>

            </telerikGrid:RadGridView>

 

            <StackPanel Grid.Row="2"

                        Margin="2"

                        Orientation="Horizontal"

                        HorizontalAlignment="Center">

                <telerik:RadButton Name="filterButton"

                                  Click="OnApplyFiltersButtonClick"

                                  Content="Apply Filters"

                                  Margin="2"

                                  Width="96"/>

                <telerik:RadButton Name="clearButton"

                                  Click="OnClearFiltersButtonClick"

                                  Content="Clear Filters"

                                  Margin="2"

                                  Width="96"/>

            </StackPanel>

 

        </Grid>

 

    </Border>

</UserControl>

 

And the code-behind:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

using Telerik.Windows.Controls.GridView;

using System.Windows.Data;

using Telerik.Windows.Controls;

using Telerik.Windows.Data;

 

namespace PureServerSideFiltering

{

    /// <summary>

    /// A custom filtering control capable of filtering purely server-side.

    /// </summary>

    public partial class DomainDataSourceFilteringControl : UserControl, IFilteringControl

    {

        // The main player here.

        DomainDataSource domainDataSource;

 

        // This is the name of the property that this column displays.

        private string dataMemberName;

 

        // This is the type of the property that this column displays.

        private Type dataMemberType;

 

        /// <summary>

        /// Identifies the <see cref="IsActive"/> dependency property.

        /// </summary>

        /// <remarks>

        /// The state of the filtering funnel (i.e. full or empty) is bound to this property.

        /// </remarks>

        public static readonly DependencyProperty IsActiveProperty =

            DependencyProperty.Register(

                "IsActive",

                typeof(bool),

                typeof(DomainDataSourceFilteringControl),

                new PropertyMetadata(false));

 

        /// <summary>

        /// Gets or sets a value indicating whether the filtering is active.

        /// </summary>

        /// <remarks>

        /// Set this to true if you want to lit-up the filtering funnel.

        /// </remarks>

        public bool IsActive

        {

            get { return (bool)GetValue(IsActiveProperty); }

            set { SetValue(IsActiveProperty, value); }

        }

 

        /// <summary>

        /// Gets or sets the domain data source.

        /// We need this in order to work on its FilterDescriptors collection.

        /// </summary>

        /// <value>The domain data source.</value>

        public DomainDataSource DomainDataSource

        {

            get { return this.domainDataSource; }

            set { this.domainDataSource = value; }

        }

 

        public System.Windows.Data.FilterDescriptorCollection FilterDescriptors

        {

            get { return this.DomainDataSource.FilterDescriptors; }

        }

 

        public DomainDataSourceFilteringControl()

        {

            InitializeComponent();

        }

 

        public void Prepare(GridViewBoundColumnBase column)

        {

            this.LayoutRoot.DataContext = this;

 

            if (this.DomainDataSource == null)

            {

                // Sorry, but we need a DomainDataSource. Can't do anything without it.

                return;

            }

 

            // This is the name of the property that this column displays.

            this.dataMemberName = column.GetDataMemberName();

 

            // This is the type of the property that this column displays.

            // We need this in order to see which FilterOperators to feed to the combo-box column.

            this.dataMemberType = column.DataType;

 

            // We will use our magic Type extension method to see which operators are applicable for

            // this data type. You can go to the extension method body and see what it does.

            ((GridViewComboBoxColumn)this.filtersGrid.Columns["Operator"]).ItemsSource

                = this.dataMemberType.ApplicableFilterOperators();

 

            // This is very nice as well. We will tell the Value column its data type. In this way

            // RadGridView will pick up the best editor according to the data type. For example,

            // if the data type of the value is DateTime, you will be editing it with a DatePicker.

            // Nice!

            ((GridViewDataColumn)this.filtersGrid.Columns["Value"]).DataType = this.dataMemberType;

 

            // Yet another nice feature. We will transfer the original DataFormatString (if any) to

            // the Value column. In this way if you have specified a DataFormatString for the original

            // column, you will see all filter values formatted accordingly.

            ((GridViewDataColumn)this.filtersGrid.Columns["Value"]).DataFormatString = column.DataFormatString;

 

            // This is important. Since our little filtersGrid will be bound to the entire collection

            // of this.domainDataSource.FilterDescriptors, we need to set a Telerik filter on the

            // grid so that it will display FilterDescriptor which are relevane to this column ONLY!

            Telerik.Windows.Data.FilterDescriptor columnFilter = new Telerik.Windows.Data.FilterDescriptor("PropertyPath"

                , Telerik.Windows.Data.FilterOperator.IsEqualTo

                , this.dataMemberName);

            this.filtersGrid.FilterDescriptors.Add(columnFilter);

 

            // We want to listen for this in order to activate and de-activate the UI funnel.

            this.filtersGrid.Items.CollectionChanged += this.OnFilterGridItemsCollectionChanged;

        }

 

        /// <summary>

        // Since the DomainDataSource is a little bit picky about adding uninitialized FilterDescriptors

        // to its collection, we will prepare each new instance with some default values and then

        // the user can change them later. Go to the event handler to see how we do this.

        /// </summary>

        void OnFilterGridAddingNewDataItem(object sender, GridViewAddingNewEventArgs e)

        {

            // We need to initialize the new instance with some values and let the user go on from here.

            System.Windows.Data.FilterDescriptor newFilter = new System.Windows.Data.FilterDescriptor();

 

            // This is a must. It should know what member it is filtering on.

            newFilter.PropertyPath = this.dataMemberName;

 

            // Initialize it with one of the allowed operators.

            // TypeExtensions.ApplicableFilterOperators method for more info.

            newFilter.Operator = this.dataMemberType.ApplicableFilterOperators().First();

 

            if (this.dataMemberType == typeof(DateTime))

            {

                newFilter.Value.Value = DateTime.Now;

            }

            else if (this.dataMemberType == typeof(string))

            {

                newFilter.Value.Value = "<enter text>";

            }

            else if (this.dataMemberType.IsValueType)

            {

                // We need something non-null for all value types.

                newFilter.Value.Value = Activator.CreateInstance(this.dataMemberType);

            }

 

            // Let the user edit the new filter any way he/she likes.

            e.NewObject = newFilter;

        }

 

        void OnFilterGridItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)

        {

            // We are active only if we have any filters define. In this case the filtering funnel will lit-up.

            this.IsActive = this.filtersGrid.Items.Count > 0;

        }

 

        private void OnApplyFiltersButtonClick(object sender, RoutedEventArgs e)

        {

            if (this.DomainDataSource.IsLoadingData)

            {

                return;

            }

 

            // Comment this if you want the popup to stay open after the button is clicked.

            this.ClosePopup();

 

            // Since this.domainDataSource.AutoLoad is false, this will take into

            // account all filtering changes that the user has made since the last

            // Load() and pull the new data to the client.

            this.DomainDataSource.Load();

        }

 

        private void OnClearFiltersButtonClick(object sender, RoutedEventArgs e)

        {

            if (this.DomainDataSource.IsLoadingData)

            {

                return;

            }

 

            // We want to remove ONLY those filters from the DomainDataSource

            // that this control is responsible for.

            this.DomainDataSource.FilterDescriptors

                .Where(fd => fd.PropertyPath == this.dataMemberName) // Only "our" filters.

                .ToList()

                .ForEach(fd => this.DomainDataSource.FilterDescriptors.Remove(fd)); // Bye-bye!

 

            // Comment this if you want the popup to stay open after the button is clicked.

            this.ClosePopup();

 

            // After we did our housekeeping, get the new data to the client.

            this.DomainDataSource.Load();

        }

 

        private void OnAddFilterButtonClick(object sender, RoutedEventArgs e)

        {

            if (this.DomainDataSource.IsLoadingData)

            {

                return;

            }

 

            // Let the user enter his/or her requirements for a new filter.

            this.filtersGrid.BeginInsert();

            this.filtersGrid.UpdateLayout();

        }

 

        private void OnRemoveFilterButtonClick(object sender, RoutedEventArgs e)

        {

            if (this.DomainDataSource.IsLoadingData)

            {

                return;

            }

 

            // Find the currently selected filter and destroy it.

            System.Windows.Data.FilterDescriptor filterToRemove = this.filtersGrid.SelectedItem as System.Windows.Data.FilterDescriptor;

            if (filterToRemove != null

                && this.DomainDataSource.FilterDescriptors.Contains(filterToRemove))

            {

                this.DomainDataSource.FilterDescriptors.Remove(filterToRemove);

            }

        }

 

        private void ClosePopup()

        {

            System.Windows.Controls.Primitives.Popup popup = this.ParentOfType<System.Windows.Controls.Primitives.Popup>();

            if (popup != null)

            {

                popup.IsOpen = false;

            }

        }

    }

}

 

Finally, we need to tell RadGridView’s Columns to use this custom control instead of the default one. Here is how to do it:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

using System.Windows.Data;

using Telerik.Windows.Data;

using Telerik.Windows.Controls;

using Telerik.Windows.Controls.GridView;

 

namespace PureServerSideFiltering

{

    public partial class MainPage : UserControl

    {

        public MainPage()

        {

            InitializeComponent();

            this.grid.AutoGeneratingColumn += this.OnGridAutoGeneratingColumn;

 

            // Uncomment this if you want the DomainDataSource to start pre-filtered.

            // You will notice how our custom filtering controls will correctly read this information,

            // populate their UI with the respective filters and lit-up the funnel to indicate that

            // filtering is active. Go ahead and try it.

            this.employeesDataSource.FilterDescriptors.Add(new System.Windows.Data.FilterDescriptor("Title", System.Windows.Data.FilterOperator.Contains, "Assistant"));

            this.employeesDataSource.FilterDescriptors.Add(new System.Windows.Data.FilterDescriptor("HireDate", System.Windows.Data.FilterOperator.IsGreaterThan, new DateTime(1998, 12, 31)));

            this.employeesDataSource.FilterDescriptors.Add(new System.Windows.Data.FilterDescriptor("HireDate", System.Windows.Data.FilterOperator.IsLessThanOrEqualTo, new DateTime(1999, 12, 31)));

 

            this.employeesDataSource.Load();

        }

 

        /// <summary>

        /// First of all, we will need to replace the default filtering control

        /// of each column with out custom filtering control DomainDataSourceFilteringControl

        /// </summary>

        private void OnGridAutoGeneratingColumn(object sender, GridViewAutoGeneratingColumnEventArgs e)

        {

            GridViewBoundColumnBase dataColumn = e.Column as GridViewBoundColumnBase;

            if (dataColumn != null)

            {

                // We do not like ugly dates.

                if (dataColumn.DataType == typeof(DateTime))

                {

                    dataColumn.DataFormatString = "{0:d}"; // Short date pattern.

 

                    // Notice how this format will be later transferred to the Value column

                    // of the grid that we have inside the DomainDataSourceFilteringControl.

                }

 

                // Replace the default filtering control with our.

                dataColumn.FilteringControl = new DomainDataSourceFilteringControl()

                {

                    // Let the control know about the DDS, after all it will work directly on it.

                    DomainDataSource = this.employeesDataSource

                };

 

                // Finally, lit-up the filtering funnel through the IsActive dependency property

                // in case there are some filters on the DDS that match our column member.

                string dataMemberName = dataColumn.GetDataMemberName();

                dataColumn.FilteringControl.IsActive =

                    this.employeesDataSource.FilterDescriptors

                    .Where(fd => fd.PropertyPath == dataMemberName)

                    .Count() > 0;

            }

        }

    }

}

The best part is that we are not only writing filters for the DomainDataSource – we can read and load them. If the DomainDataSource has some pre-existing filters (like I have created in the code above), our control will read them and will populate its UI accordingly. Even the filtering funnel will light-up! Remember, the funnel is controlled by the IsActive property of our control.

While this is just a basic implementation, the source code is absolutely yours and you can take it from here and extend it to match your specific business requirements.

Below the main grid there is another debug grid. With its help you can monitor what filter descriptors are added and removed to the domain data source.

Download Source Code. (You will have to have the AdventureWorks sample database installed on the default SQLExpress instance in order to run it.)

Enjoy!

25 Comments

  • Surya 09 Apr 2010
    Rossen,

    Can you please update the Source Code zip file? When we download and try to open the current one, the zip file has errors and is showing up empty.

    Many thanks...
  • Surya 09 Apr 2010
    Rossen,

    Never mind, for some reason, it was the downloaded zip file was not opening in WinZip, however the same opened fine in 7-Zip.

    Thanks & Regards...
  • Mike 11 May 2010
    Rossen,
    Thanks for the excellent post.  I have a question about this I was hoping you could answer.

    Instead of using auto-generated columns, I want to use columns that are defined in the XAML.  I've taken your example and added the DomainDataSourceFilteringControl to my project.  Then I added some code to the myTable_RowLoaded function that assigns the new custom filtering control to each of my column headers in the table.  This seems to work fine.  When I run the application, the default filter control is replaced by your filtering control.

    The only problem I'm having is that the filter funnel never lights up (shows active) when filters are applied to the column.  The filter is applied and the updated query reflects this, but there is no indicator to show that filtering has been applied.

    If I switch back to auto-generating the columns, the funnel lights up appropriately.

    Any idea what I'm doing wrong or what I need to do to fix this.  I really don't want to display all of the columns from my query.

    Thanks,
    Mike
  • Rossen Hristov 12 May 2010
    Hello Mike,

    Can you please open a support ticket and send me your sample project. I will take a look at it and see what is wrong. Thanks in advance.
  • Miguel Luna 14 Jun 2010
    Hello,

    Adding a filter, in the Value Column, I insert the value and when I finish the edition of the field (pressing enter key), the value disapears. Adding a new filter disapears too.

    Thanks in advance.
  • Miguel Luna 14 Jun 2010
    Hi again,

    I had changed all the reference from System.Windows.Data.FilterDescriptor to System.Windows.Controls.FilterDescritor and I forgot change the binding in xaml control


      <telerikGrid:RadGridView.Columns>
                        <telerikGrid:GridViewComboBoxColumn DataMemberBinding="{Binding Operator}"
                                                            UniqueName="Operator"/>
                        <telerikGrid:GridViewDataColumn Header="Value"
                                                        DataMemberBinding="{Binding Value.Value}"
                                                        UniqueName="Value"/>
                    </telerikGrid:RadGridView.Columns>

    Just change "Value.Value" to "Value" and it's work.

    Thanks,
    Miguel
  • Mirin 02 Jul 2010
    Hello!!

    I´ve got a dude, if the filter show "IsLessThan","Contains"..etc..If I want to show "EsMenorQue","Contiene"...that´s in Spanish, How i could do that? Resources?? How?
    Very thanksss!!

    rgonzalezva@uoc.edu
  • Rossen Hristov 06 Jul 2010
    Hello Mirin,

    You can find more information about localization here.

    I hope this helps.
  • Gopesh 16 Jul 2010
    Hi Rossen, 

     Can you please update source code again. I am unable to extract the source code from Zip folder. It says either file is damaged or corrupted. 

    Many Many Thanks.
  • Rossen Hristov 16 Jul 2010
    Hello Gopesh,

    Can you try with the 7-zip program (it's free). Other people said that this helped them. Let me know if it does not open with 7-zip.
  • Andrew Lindzon 21 Jul 2010
    This is a great idea, is it something you could include in RadGridView as a property, making it seamless, then we would just turn it on with ServerSideFiltering="True" when establishing a grid.

    Is there any reason why this feature could not be added to the existing control?

  • Rossen Hristov 21 Jul 2010
    Hello Andrew,

    We will never do this and there is a reason. As developers we are doing our best NOT TO write tightly coupled components. Especially if they are tightly coupled with another vendor's specific implementation.

    For everyone out there thee notion of a server-side filtering could mean a completely different thing. The DomainDataSource control is a concrete implementation provided by concrete vendor (Microsoft).

    If you own a control, would you create a property (!!!) that would couple it forever with a specific implementation of a specific vendor that is not even under you control. I seriously doubt it.
  • Andrew Lindzon 21 Jul 2010
    I would not suggest you replace your current capabilities with ones that are solely tied to RIA, but I would suggest that you implement your server side filtering concepts in a way that they can be used with your datagrid as an option.

    You support RIA, why not take advantage of the filterdescriptors?

  • Andrew Lindzon 22 Jul 2010
    I am trying to review your code but I cannot open the ZIP file, and I have installed 7 zip, so three different programs which I have all say the file is corrupt.

    Can you perhaps make a new copy?
  • Andrew Lindzon 22 Jul 2010
    I got your file unzipped with the beta version of 7 zip.

    How would your code need to be changed if the columns are NOT autogenerating?

    I am referring to the code behind where you replace your filters with filtering control DomainDataSourceFilteringControl

    private

     

     

    void OnGridAutoGeneratingColumn(object sender, GridViewAutoGeneratingColumnEventArgs e)

     


    Is there an alternative for nonautogenerating columns, perhaps they need to be set manually?
  • Andrew Lindzon 22 Jul 2010

    I notice the comment from Miguel Luna above also refers to a way to apply to filters to individual columns rather than autogenerated ones.  I am not clear what commands I would need to add to do this.  Here is what my column definitions look like at present.

     

    <telerik:RadGridView.Columns>

     

     

     

    <telerik:GridViewDataColumn DataMemberBinding="{Binding CustID}" IsReadOnly="True" />

     

     

    <telerik:GridViewDataColumn DataMemberBinding="{Binding Company}"/>

     

    ...
    </telerik:GridViewColumn>

     

     

     

    What do I need to add to change the header to the server side filter?

    Also on a side note, is there any way to add a text box to the grid itself to hold specific filters, like a startwith or includes filter for the column?  If there is any way to add a feature like this either in the header or in the grid, that would be awesome.

    From a user interface perspective its the fastest way to get the most popular filters, and they can be executed as the user types.

    And one more question, how do you get rid of the area for grouping for tables where it is not required?  Is there an option to turn that off?  I am referring to the area above the heading where you drag the ones you want to group by.

    Once I figure out the server side filtering, I am prepared to move ahead with using your tools at my company.  I am very impressed with how quickly your firm responds to these posts.  The support and concern for the community is excellent.

  • Rossen Hristov 22 Jul 2010
    Hello Andrew,

    Please submit this as a support ticket. I prefer handling such things in the support ticket system, because it is much more convenient. Thanks.
  • Gareth Parris 10 Sep 2010


    Has anyone got the example above working with the latest release of Silverlight and RIA Services. I'm almost there but stuck with the following error:


    Error 1 'System.Windows.Controls.FilterDescriptorCollection' does not contain a definition for 'Where' and
    the best extension method overload 'Telerik.Windows.Data.QueryableExtensions.Where(System.Linq.IQueryable, Telerik.Windows.Data.FilterDescriptorCollection)' has some invalid arguments


                    dataColumn.FilteringControl.IsActive = 
                        this.ProductDS.FilterDescriptors 
                        .Where(fd => fd.PropertyPath == dataMemberName) 
                        .Count() > 0; 

  • Berthold 22 Sep 2010
    I'm not able to open the ZIP file with winZip 12
    Any suggestions?
  • Rossen Hristov 23 Sep 2010
    Can you try with 7-Zip? It's free.
  • Rossen Hristov 23 Sep 2010
    Can you try with 7-Zip? It's free.
  • Sarah 10 Dec 2010
    I'm trying this in my project but I get a NullReferenceException when pressing the New Filter button. Any suggestions?
  • Prakash 11 Dec 2010
    Hello Sarah,

    My suggestion would be to use the Visual Studio Debugger and see what is causing the NullReferenceException.

  • Tadeusz 13 Oct 2011
    The zip file is broken because it has plenty of padding zeros at the end.
  • Rossen 13 Oct 2011
    Can you try with 7-Zip? It's free.

Add comment

  1. Formatting options
       
     
     
     
     
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)