Added 21st post.
This commit is contained in:
Родитель
923509e8e5
Коммит
f71cd46116
|
@ -0,0 +1,78 @@
|
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{FBB02358-E0FB-4E1C-97B9-62521875C0A5}</ProjectGuid>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<RootNamespace>CustomSorting</RootNamespace>
|
||||
<AssemblyName>CustomSorting</AssemblyName>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<OutputType>winexe</OutputType>
|
||||
<ApplicationVersion>1.0.0.*</ApplicationVersion>
|
||||
<!-- Most people will use Publish dialog in Visual Studio to increment this -->
|
||||
<BootstrapperEnabled>false</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>.\bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>.\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="UIAutomationProvider" />
|
||||
<Reference Include="UIAutomationTypes" />
|
||||
<Reference Include="ReachFramework" />
|
||||
<Reference Include="System.Printing" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.IdentityModel" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="MyApp.xaml" />
|
||||
<Page Include="Window1.xaml" />
|
||||
<Compile Include="MyApp.xaml.cs">
|
||||
<DependentUpon>MyApp.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Window1.xaml.cs">
|
||||
<DependentUpon>Window1.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSorting", "CustomSorting.csproj", "{FBB02358-E0FB-4E1C-97B9-62521875C0A5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{FBB02358-E0FB-4E1C-97B9-62521875C0A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FBB02358-E0FB-4E1C-97B9-62521875C0A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FBB02358-E0FB-4E1C-97B9-62521875C0A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FBB02358-E0FB-4E1C-97B9-62521875C0A5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Двоичный файл не отображается.
|
@ -0,0 +1,9 @@
|
|||
<Application x:Class="CustomSorting.MyApp"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="Window1.xaml"
|
||||
>
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Data;
|
||||
using System.Xml;
|
||||
using System.Configuration;
|
||||
|
||||
namespace CustomSorting
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MyApp.xaml
|
||||
/// </summary>
|
||||
|
||||
public partial class MyApp : Application
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#region Using directives
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Resources;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#endregion
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CustomSorting")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CustomSorting")]
|
||||
[assembly: AssemblyCopyright("Copyright @ 2006")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
|
@ -0,0 +1,70 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <autogenerated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.42
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </autogenerated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace CustomSorting.Properties
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the Strongly Typed Resource Builder
|
||||
// class via a tool like ResGen or Visual Studio.NET.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
class Resources
|
||||
{
|
||||
|
||||
private static System.Resources.ResourceManager _resMgr;
|
||||
|
||||
private static System.Globalization.CultureInfo _resCulture;
|
||||
|
||||
/*FamANDAssem*/
|
||||
internal Resources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((_resMgr == null))
|
||||
{
|
||||
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly);
|
||||
_resMgr = temp;
|
||||
}
|
||||
return _resMgr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return _resCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
_resCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -0,0 +1,42 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <autogenerated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.42
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </autogenerated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace CustomSorting.Properties
|
||||
{
|
||||
public partial class Settings : System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
private static Settings m_Value;
|
||||
|
||||
private static object m_SyncObject = new object();
|
||||
|
||||
public static Settings Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((Settings.m_Value == null))
|
||||
{
|
||||
System.Threading.Monitor.Enter(Settings.m_SyncObject);
|
||||
if ((Settings.m_Value == null))
|
||||
{
|
||||
try
|
||||
{
|
||||
Settings.m_Value = new Settings();
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.Threading.Monitor.Exit(Settings.m_SyncObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Settings.m_Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version='1.0' encoding='iso-8859-1'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
|
@ -0,0 +1,40 @@
|
|||
<Window x:Class="CustomSorting.Window1"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="CustomSorting"
|
||||
SizeToContent="WidthAndHeight"
|
||||
xmlns:local="clr-namespace:CustomSorting"
|
||||
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
|
||||
>
|
||||
<!-- Ascending order will result in the following order: 10 - 19, 1, 20, 21, 2 - 9 -->
|
||||
<!--<Window.Resources>
|
||||
<local:BlogPosts x:Key="source"/>
|
||||
|
||||
<CollectionViewSource Source="{StaticResource source}" x:Key="cvs">
|
||||
<CollectionViewSource.SortDescriptions>
|
||||
<scm:SortDescription Direction="Ascending"/>
|
||||
</CollectionViewSource.SortDescriptions>
|
||||
</CollectionViewSource>
|
||||
</Window.Resources>
|
||||
|
||||
<StackPanel>
|
||||
<Border Margin="30" BorderBrush="Blue" BorderThickness="2" Padding="10">
|
||||
<ListBox ItemsSource="{Binding Source={StaticResource cvs}}"/>
|
||||
</Border>
|
||||
</StackPanel>-->
|
||||
|
||||
<Window.Resources>
|
||||
<local:BlogPosts x:Key="posts"/>
|
||||
|
||||
<Style TargetType="{x:Type ListBoxItem}" x:Key="containerStyle">
|
||||
<Setter Property="Margin" Value="0,5,0,0" />
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<Border Margin="30" BorderBrush="Blue" BorderThickness="2" Padding="10">
|
||||
<StackPanel>
|
||||
<ListBox ItemsSource="{StaticResource posts}" ItemContainerStyle="{StaticResource containerStyle}" Name="lb"/>
|
||||
<Button Click="Sort" Content="Sort" Margin="0,10,0,0"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Window>
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace CustomSorting
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Window1.xaml
|
||||
/// </summary>
|
||||
|
||||
public partial class Window1 : Window
|
||||
{
|
||||
|
||||
public Window1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Sort(object sender, RoutedEventArgs args)
|
||||
{
|
||||
BlogPosts posts = (BlogPosts)(this.Resources["posts"]);
|
||||
ListCollectionView lcv = (ListCollectionView)(CollectionViewSource.GetDefaultView(posts));
|
||||
lcv.CustomSort = new SortPosts();
|
||||
}
|
||||
}
|
||||
|
||||
public class SortPosts : IComparer
|
||||
{
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
string str1 = x.ToString();
|
||||
string str2 = y.ToString();
|
||||
|
||||
int int1 = GetNumberAtBeginning(str1);
|
||||
int int2 = GetNumberAtBeginning(str2);
|
||||
|
||||
// strings start with same number or don't start with numbers
|
||||
if (int1 == int2)
|
||||
{
|
||||
return str1.CompareTo(str2); // compare the strings
|
||||
}
|
||||
// strings start with different numbers
|
||||
else if ((int1 != -1) && (int2 != -1))
|
||||
{
|
||||
return int1.CompareTo(int2); // compare the numbers
|
||||
}
|
||||
// first string does not start with number
|
||||
else if (int1 == -1)
|
||||
{
|
||||
return 1; // second string goes first
|
||||
}
|
||||
// second string does not start with number
|
||||
else
|
||||
{
|
||||
return -1; // first string goes first
|
||||
}
|
||||
}
|
||||
|
||||
private int GetNumberAtBeginning(string str)
|
||||
{
|
||||
// see if the string begins with a number
|
||||
if (string.IsNullOrEmpty(str) || !char.IsDigit(str[0]))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// parse the number at the beginning of the string
|
||||
int result = 0;
|
||||
foreach (char c in str)
|
||||
{
|
||||
if (char.IsDigit(c))
|
||||
{
|
||||
result = result * 10 + c - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class BlogPosts : ObservableCollection<string>
|
||||
{
|
||||
public BlogPosts()
|
||||
{
|
||||
this.Add("14SortingGroups");
|
||||
this.Add("21CustomSorting");
|
||||
this.Add("2EmptyBinding");
|
||||
this.Add("3GetListBoxItem");
|
||||
this.Add("12DataBoundDialogBox");
|
||||
this.Add("4BindToComboBox");
|
||||
this.Add("16GroupByType");
|
||||
this.Add("9CollectionViewSourceSample");
|
||||
this.Add("19ObjectDataProviderSample");
|
||||
this.Add("20InsertingSeparators");
|
||||
this.Add("5DisplayMemberPath");
|
||||
this.Add("7ChangePanelItemsControl");
|
||||
this.Add("8BarGraph");
|
||||
this.Add("10MasterDetail");
|
||||
this.Add("1DataContextSample");
|
||||
this.Add("6SelectedValue");
|
||||
this.Add("13TemplatingItems");
|
||||
this.Add("18ThreeLevelMasterDetailADO");
|
||||
this.Add("15GroupingTreeView");
|
||||
this.Add("11MasterDetailThreeLevels");
|
||||
this.Add("17BoundListView");
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 20 KiB |
|
@ -0,0 +1,48 @@
|
|||
# How to add custom sorting logic
|
||||
|
||||
I showed in an <a href="http://www.zagstudio.com/blog/362">earlier post</a> how we can use CollectionViewSource to sort items in markup. This way of sorting allows us to pick Ascending or Descending sorting, but it doesn't provide any flexibility beyond that. Today I will show you how you can write your own sorting logic that enables full control over the order of items in a view.
|
||||
|
||||
When I write a new blog sample, I create a directory named with a number followed by a short description of the scenario. For example, for today's post, the name of the directory is 21CustomSorting. Windows Explorer knows how to do the right thing to order all those directories: the first one is 1DataContext, and all the others are displayed in increasing numeric order until 21CustomSorting. This is not a simple ascending string sort, though. A traditional string sort would display 10MasterDetail - 19ObjectDataProviderSample, 1DataContext, 20InsertingSeparators, 21CustomSorting, 2EmptyBinding - 9CollectionViewSourceSample, which is obviously not what I want. I will show you today how you can order strings that start with numbers the same way as Explorer. I will also give you a quick overview of Avalon's view classes.
|
||||
|
||||
A view is a layer on top of a collection that allows us to sort, filter and group the collection. Views also remember the current item of a collection, which is useful for the master-detail scenario. The base class for all views is CollectionView, which is where we keep the API for sorting, filtering, grouping and current item. There are currently two classes that derive from CollectionView: BindingListCollectionView and ListCollectionView. The view type we create internally depends on the type of your source collection:
|
||||
|
||||
- A CollectionView is created if your source implements IEnumerable. If the source implements IEnumerable *only*, you will not be able to sort or group the collection (you can only filter it). Also, perf will not be the best if the source has a large number of items or if you perform dynamic operations such as insertions and deletions. If this is your scenario, you should consider having your source implement a stronger interface. ICollection is slightly better because it provides a Count property.
|
||||
|
||||
- ListCollectionView is the view type created when the source implements IList. Compared to IEnumerable and ICollection, IList performs much better for large or dynamic lists because it provides an indexer, allowing us quick random access. In addition, IList allows sorting, grouping and filtering. But ideally your source collection derives from ObservableCollection<T>, the mother of all collections in the eyes of data binding, since it provides several extra goodies such as property and collection change notifications.
|
||||
|
||||
- BindingListCollectionView is the type of view created by Avalon when the source collection implements IBindingList. This is the view we deal with in the ADO.NET scenario. It supports sorting and grouping, but not traditional filtering. Instead, it has an additional CustomFilter property that delegates filtering to the DataView (see <a href="http://www.zagstudio.com/blog/372">my post on ADO.NET</a> for more details).
|
||||
|
||||
Note that if your source collection implements both IBindingList and IList, IBindingList has priority, and a BindingListCollectionView is created.
|
||||
|
||||
ListCollectionView has an extra CustomSort property that allows us to provide our own sorting logic, which is what I will show you next. The source collection for this sample is an ObservableCollection<string> of the directory names that I use for my blog posts. The UI of this sample contains a ListBox of blog post directory names, initially in random order, and a "Sort" Button:
|
||||
|
||||
<Window.Resources>
|
||||
<local:BlogPosts x:Key="posts"/>
|
||||
(...)
|
||||
</Window.Resources>
|
||||
|
||||
<ListBox ItemsSource="{StaticResource posts}" (...) Name="lb"/>
|
||||
<Button Click="Sort" Content="Sort" Margin="0,10,0,0"/>
|
||||
|
||||
When the user clicks the "Sort" button, we get the default view for the source collection, cast it to ListCollectionView, and give it some custom sort logic. The GetDefaultView method returns a CollectionView, but we can cast it to ListCollectionView because we know that the BlogPosts source collection implements IList.
|
||||
|
||||
private void Sort(object sender, RoutedEventArgs args)
|
||||
{
|
||||
BlogPosts posts = (BlogPosts)(this.Resources["posts"]);
|
||||
ListCollectionView lcv = (ListCollectionView)(CollectionViewSource.GetDefaultView(posts));
|
||||
lcv.CustomSort = new SortPosts();
|
||||
}
|
||||
|
||||
The CustomSort property is of type IComparer. We need to create a new class that implements IComparer, and add our sorting logic to its Compare method. This method should return a negative number if x comes before y, a positive number if x comes after y, and zero if they are equivalent.
|
||||
|
||||
public class SortPosts : IComparer
|
||||
{
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
(...)
|
||||
}
|
||||
}
|
||||
|
||||
Here is a screenshot of the completed sample:
|
||||
|
||||
![](Images/21CustomSorting.png)
|
Загрузка…
Ссылка в новой задаче