// Verify if the data that will be sorted can be compared
        bool VerifyComparable(PropertySortDescription operation)
        {
            if (operation.Comparer == null) // not null here means that the user wants to use a custom comparer
            {
                if (Items.Count != 0)
                {
#if OPENSILVER
                    if (true)
#elif BRIDGE
                    if (CSHTML5.Interop.IsRunningInTheSimulator)
#endif
                    {
                        Type type = GetValue(Items.ElementAt(0), operation).GetType();

                        if (typeof(IComparable).IsAssignableFrom(type))
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        //--------------------
                        // HACK: in JavaScript, since Comparer does not work properly in JSIL, we attempt to compare dynamic values and see if it passes the try/catch.
                        //--------------------

                        // We try to do a comparaison between the same object to see if js allows comparison (fail has not been tested...)
                        try
                        {
                            // basics types
                            dynamic value1ToCompare = GetValue(Items.ElementAt(0), operation);
                            dynamic value2ToCompare = value1ToCompare;

                            if (value1ToCompare > value2ToCompare)
                            {
                            }

                            return(true);
                        }
                        catch
                        {
                            /*
                             * // custom types (see also __comparer__ in jsil)
                             * Type type = GetValue(Items.ElementAt(0), operation).GetType();
                             *
                             * foreach (MethodInfo method in type.GetMethods())
                             * {
                             *  if (method.Name == "CompareTo")
                             *      return true;
                             * }
                             */

                            return(false);
                        }
                    }
                }
                return(false);
            }

            throw new NotImplementedException("Custom Sorting is not supported yet");
        }
Example #2
0
        // return the true direction to use to fix the sorting cascade problem, which is that when there are multiple sort operations, all their directions are inversed, for unknown reason, probably due to the currently used sort algorithm.
        public ListSortDirection GetFixedDirection(PropertySortDescription operation)
        {
            int index = _collectionViewer.SortDescriptions.IndexOf(operation);

            if (index % 2 == 0 && _collectionViewer.SortDescriptions.Count > 1)
            {
                return(operation.Direction == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending); // invert
            }
            return(operation.Direction);                                                                                                 // normal
        }
Example #3
0
        public void PropertySortDescription_DefaultValues()
        {
            PropertySortDescription psd = new PropertySortDescription();

            Assert.AreEqual(SortOrder.Ascending, psd.SortOrder);
            Assert.IsTrue(string.IsNullOrWhiteSpace(psd.CustomName));
            Assert.IsTrue(string.IsNullOrWhiteSpace(psd.PropertyName));
            Assert.IsNull(psd.MemberAccess);
            Assert.AreEqual(psd.PropertyName, psd.GetMemberName());
        }
        // Sort the data source with a default comparer
        void Sort(PropertySortDescription operation)
        {
            if (VerifyComparable(operation))// if we can't compare data, we don't try to sort
            {
                ListSortDirection directionBackup = operation.Direction;

                operation.Direction = _operations.GetFixedDirection(operation);

                Collection <object> childItems = new Collection <object>();

                //todo: replace with a sort algorithm that is O(NLogN), for example by creating a List<T> and calling List<T>.Sort(comparer).

                foreach (object item in Items)
                {
                    int index;

                    // we get the value of the sorting property on this item to allow comparison (if we are here, we know that data is comparable)
                    // then we get the position where we need to insert this item
#if OPENSILVER
                    if (true)
#elif BRIDGE
                    if (CSHTML5.Interop.IsRunningInTheSimulator)
#endif
                    {
                        IComparable value = (IComparable)GetValue(item, operation);

                        index = GetPosIndex_SimulatorOnly(operation, value, 0, childItems.Count, childItems);
                    }
                    else
                    {
                        dynamic value = GetValue(item, operation);

                        index = GetPosIndex_JSOnly(operation, value, 0, childItems.Count, childItems);
                    }

                    childItems.Insert(index, item);
                }

                operation.Direction = directionBackup;

                // Pass the result of the sort to a child CollectionViewGroup in order to apply other operations (such as sort) if any:
                INTERNAL_CollectionViewGroupInternal newView = new INTERNAL_CollectionViewGroupInternal(childItems, this, _operations);
                _operations.Requester.AddView(newView); // create child branch after sorting operation
            }
            else
            {
                INTERNAL_CollectionViewGroupInternal newView = new INTERNAL_CollectionViewGroupInternal(Items, this, _operations);
                _operations.Requester.AddView(newView); // create child branch without sorting
            }
        }
Example #5
0
        // Execute the next operation requested in the operations list
        void ExecuteOperation(object operation)
        {
            if (operation != null)
            {
                IsLeaf = false;

                if (operation is FilterDescription)
                {
                    FilterDescription filterOperation = (FilterDescription)operation;

                    // both cannot be null and both cannot be not null
                    if (filterOperation.FilterUsingAnEvent != null)
                    {
                        Filter(filterOperation.FilterUsingAnEvent);
                    }
                    else
                    {
                        Filter(filterOperation.FilterUsingAPredicate);
                    }
                }
                else if (operation is PropertySortDescription)
                {
                    PropertySortDescription sortOperation = (PropertySortDescription)operation;

                    if (sortOperation.Comparer == null)
                    {
                        Sort(sortOperation);
                    }
                    else
                    {
                        CustomSort(sortOperation);
                    }
                }
                else if (operation is INTERNAL_PropertyGroupDescription)
                {
                    INTERNAL_PropertyGroupDescription groupOperation = (INTERNAL_PropertyGroupDescription)operation;

                    GroupBy(groupOperation);
                }
                else
                {
                    throw new InvalidOperationException("unknow operation type");
                }
            }
            else // if the operation to do on this view is null, that mean we have reach the end of the operation list and this view is usable as data source
            {
                IsLeaf = true;
            }
        }
Example #6
0
        // Get the position where the x object must be inserted in the data source of this view (simple dichotomic sorting)
        int GetPosIndex_JSOnly(PropertySortDescription operation, dynamic x, int min, int max, Collection <object> childItems)
        {
            if (min == max) // recursive end condition
            {
                return(min);
            }
            else
            {
                int middle = ((max - min) / 2) + min;

                dynamic childValue = GetValue(childItems[middle], operation);

                if (operation.Direction == ListSortDirection.Ascending ? (x > childValue) : (x < childValue))
                {
                    return(GetPosIndex_JSOnly(operation, x, middle + 1, max, childItems)); // +1 to fix the rounded int of middle
                }
                else
                {
                    return(GetPosIndex_JSOnly(operation, x, min, middle, childItems));
                }
            }
        }
Example #7
0
        // Get the position where the x object must be inserted in the data source of this view (simple dichotomic sorting)
        int GetPosIndex_SimulatorOnly(PropertySortDescription operation, IComparable x, int min, int max, Collection <object> childItems)
        {
            if (min == max) // recursive end condition
            {
                return(min);
            }
            else
            {
                int middle = ((max - min) / 2) + min;

                object childValue = GetValue(childItems[middle], operation);

                if ((operation.Direction == ListSortDirection.Ascending ? 1 : -1) * x.CompareTo(childValue) > 0) // the ternaire operation allow to swith the comparation behaviour
                {
                    return(GetPosIndex_SimulatorOnly(operation, x, middle + 1, max, childItems));                // +1 to fix the rounded int of middle
                }
                else
                {
                    return(GetPosIndex_SimulatorOnly(operation, x, min, middle, childItems));
                }
            }
        }
Example #8
0
        public void PropertySortDescription_Clone_Correctly()
        {
            PropertySortDescription psd = new PropertySortDescription();

            psd.PropertyName = "Test";
            Assert.AreEqual(psd.PropertyName, psd.DisplayName);
            psd.SortOrder  = SortOrder.Descending;
            psd.CustomName = "Custom";
            Assert.AreEqual(psd.CustomName, psd.DisplayName);

            var copy = psd.Clone() as PropertySortDescription;

            Assert.IsNotNull(copy);
            Assert.AreNotSame(psd, copy);
            Assert.IsInstanceOfType(copy, typeof(PropertySortDescription));
            Assert.AreEqual(psd.CustomName, copy.CustomName);
            Assert.AreEqual(psd.PropertyName, copy.PropertyName);
            Assert.AreEqual(psd.DisplayName, copy.DisplayName);
            Assert.AreEqual(psd.SortOrder, copy.SortOrder);
            Assert.AreEqual(psd.PropertyName, psd.GetMemberName());
            Assert.AreEqual(copy.PropertyName, copy.GetMemberName());
        }
Example #9
0
 // Get the value of the property described in operation by reflection
 object GetValue(object obj, PropertySortDescription operation)
 {
     return(obj.GetType().GetProperty(operation.PropertyName).GetValue(obj, null));
 }
Example #10
0
 void CustomSort(PropertySortDescription operation)
 {
     throw new NotImplementedException("Custom Sorting is not supported yet");
 }
Example #11
0
        public void PropertySortDescription_CustomName_Raise_DisplayName_PropertyChanged()
        {
            PropertySortDescription psd = new PropertySortDescription();

            psd.AssertPropertyChanged("Setting CustomName", () => psd.CustomName = "Test", "CustomName", "DisplayName");
        }
Example #12
0
        public void PropertySortDescription_SortOrder_Raise_PropertyChanged()
        {
            PropertySortDescription psd = new PropertySortDescription();

            psd.AssertPropertyChanged("Setting SortOrder", () => psd.SortOrder = SortOrder.Descending, "SortOrder");
        }