├── .gitignore
├── .tfignore
├── DVFilterSort.sln
├── DVFilterSort
├── App.xaml
├── App.xaml.cs
├── Converter.cs
├── CustomerProvider.cs
├── Customers.dbml
├── Customers.dbml.layout
├── Customers.designer.cs
├── CustomersDataSet.Designer.cs
├── CustomersDataSet.xsc
├── CustomersDataSet.xsd
├── CustomersDataSet.xss
├── DVFilterSort.csproj
├── DataGridHelper.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
└── app.config
├── DataVirtualization
├── AsyncVirtualizingCollection.cs
├── DataPage.cs
├── DataVirtualization.csproj
├── DataWrapper.cs
├── IItemsProvider.cs
├── Properties
│ └── AssemblyInfo.cs
└── VirtualizingCollection.cs
├── README.md
└── ReusableControls
├── DateRangePicker.xaml
├── DateRangePicker.xaml.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
└── ReusableControls.csproj
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 |
--------------------------------------------------------------------------------
/.tfignore:
--------------------------------------------------------------------------------
1 | \.git
--------------------------------------------------------------------------------
/DVFilterSort.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DVFilterSort", "DVFilterSort\DVFilterSort.csproj", "{EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReusableControls", "ReusableControls\ReusableControls.csproj", "{37EC527A-D370-4643-A4A5-F585D18244D1}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataVirtualization", "DataVirtualization\DataVirtualization.csproj", "{F0551328-4699-43B6-949E-9BDABF89FC1E}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|Mixed Platforms = Debug|Mixed Platforms
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|Mixed Platforms = Release|Mixed Platforms
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Debug|Any CPU.ActiveCfg = Debug|x86
21 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
22 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Debug|Mixed Platforms.Build.0 = Debug|x86
23 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Debug|x86.ActiveCfg = Debug|x86
24 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Debug|x86.Build.0 = Debug|x86
25 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Release|Any CPU.ActiveCfg = Release|x86
26 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Release|Mixed Platforms.ActiveCfg = Release|x86
27 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Release|Mixed Platforms.Build.0 = Release|x86
28 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Release|x86.ActiveCfg = Release|x86
29 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}.Release|x86.Build.0 = Release|x86
30 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
33 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
34 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Debug|x86.ActiveCfg = Debug|Any CPU
35 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
36 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Release|Any CPU.Build.0 = Release|Any CPU
37 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
38 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
39 | {37EC527A-D370-4643-A4A5-F585D18244D1}.Release|x86.ActiveCfg = Release|Any CPU
40 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
43 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
44 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Debug|x86.ActiveCfg = Debug|Any CPU
45 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
48 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
49 | {F0551328-4699-43B6-949E-9BDABF89FC1E}.Release|x86.ActiveCfg = Release|Any CPU
50 | EndGlobalSection
51 | GlobalSection(SolutionProperties) = preSolution
52 | HideSolutionNode = FALSE
53 | EndGlobalSection
54 | EndGlobal
55 |
--------------------------------------------------------------------------------
/DVFilterSort/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/DVFilterSort/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Windows;
7 |
8 | namespace DVFilterSort
9 | {
10 | ///
11 | /// Interaction logic for App.xaml
12 | ///
13 | public partial class App : Application
14 | {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DVFilterSort/Converter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows.Data;
6 | using System.Globalization;
7 |
8 | namespace DVFilterSort
9 | {
10 | public class DateConverter : IValueConverter
11 | {
12 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
13 | {
14 | DateTime date = (DateTime)value;
15 | return String.Format("{0:d}", date);
16 | }
17 |
18 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
19 | {
20 | throw new NotImplementedException();
21 | }
22 | }
23 |
24 | public class MoneyConverter : IValueConverter
25 | {
26 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
27 | {
28 | double money = (double)value;
29 | return String.Format("{0:c}", money);
30 | }
31 |
32 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
33 | {
34 | throw new NotImplementedException();
35 | }
36 | }
37 |
38 | public class RegionConverter : IValueConverter
39 | {
40 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
41 | {
42 | int intValue;
43 | bool parsed = Int32.TryParse(value.ToString(), out intValue);
44 | if (parsed)
45 | {
46 | USRegion region = (USRegion)(int)value;
47 | return region.ToString();
48 | }
49 | return "";
50 | }
51 |
52 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
53 | {
54 | throw new NotImplementedException();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/DVFilterSort/CustomerProvider.cs:
--------------------------------------------------------------------------------
1 | #region
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading;
7 | using DataVirtualization;
8 |
9 | #endregion
10 |
11 | namespace DVFilterSort
12 | {
13 | public class CustomerProvider : IItemsProvider
14 | {
15 | private readonly List _customers;
16 | private readonly DateTime? _dateFrom;
17 | private readonly DateTime? _dateTo;
18 | private readonly string _sortField;
19 | private int _count;
20 |
21 | public CustomerProvider()
22 | {
23 | _dateFrom = DateTime.Today.AddYears(-100);
24 | _dateTo = DateTime.Today.AddYears(100);
25 | _sortField = "CustomerSince DESC";
26 |
27 | _customers = new List();
28 | for (int i = 0; i < 10000; i++)
29 | {
30 | _customers.Add(new Customer
31 | {
32 | AmountPaidInternationalCalls = i%100,
33 | AmountPaidLocalCalls = i%100,
34 | AmountPaidNationalCalls = i%100,
35 | CustomerSince = _dateFrom.Value.AddDays(i),
36 | FirstName = string.Format("Customer {0}", i),
37 | Id = i,
38 | LastName = string.Format("LastName {0}", i),
39 | JoinedPreferredProgram = i%2 == 0,
40 | NumberFamilyMembersInPlan = i%4,
41 | Region = i%100,
42 | });
43 | }
44 | }
45 |
46 | public CustomerProvider(DateTime? dateFrom, DateTime? dateTo, string sortField)
47 | : this()
48 | {
49 | if (dateFrom != null)
50 | {
51 | _dateFrom = dateFrom;
52 | }
53 | if (dateTo != null)
54 | {
55 | _dateTo = dateTo;
56 | }
57 |
58 | _sortField = sortField;
59 | }
60 |
61 | public int FetchCount()
62 | {
63 | Thread.Sleep(1000);
64 | _count = _customers.Count(e => e.CustomerSince >= _dateFrom && e.CustomerSince <= _dateTo);
65 | return _count;
66 | }
67 |
68 | public IList FetchRange(int startIndex, int pageCount, out int overallCount)
69 | {
70 | Thread.Sleep(500);
71 |
72 | overallCount = _count; // In this case it's ok not to get the count again because we're assuming the data in the database is not changing.
73 |
74 | if (_sortField.Contains("DESC"))
75 |
76 | return _customers.Where(e => e.CustomerSince >= _dateFrom && e.CustomerSince <= _dateTo)
77 | .OrderBy(e => e.FirstName)
78 | .Skip(startIndex)
79 | .Take(pageCount).ToList();
80 | else
81 | return _customers.Where(e => e.CustomerSince >= _dateFrom && e.CustomerSince <= _dateTo)
82 | .OrderByDescending(e => e.FirstName)
83 | .Skip(startIndex)
84 | .Take(pageCount).ToList();
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/DVFilterSort/Customers.dbml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/DVFilterSort/Customers.dbml.layout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/DVFilterSort/Customers.designer.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable 1591
2 | //------------------------------------------------------------------------------
3 | //
4 | // This code was generated by a tool.
5 | // Runtime Version:4.0.21006.1
6 | //
7 | // Changes to this file may cause incorrect behavior and will be lost if
8 | // the code is regenerated.
9 | //
10 | //------------------------------------------------------------------------------
11 |
12 | namespace DVFilterSort
13 | {
14 | using System.Data.Linq;
15 | using System.Data.Linq.Mapping;
16 | using System.Data;
17 | using System.Collections.Generic;
18 | using System.Reflection;
19 | using System.Linq;
20 | using System.Linq.Expressions;
21 | using System.ComponentModel;
22 | using System;
23 |
24 |
25 | [global::System.Data.Linq.Mapping.DatabaseAttribute(Name="Customers")]
26 | public partial class CustomersDataContext : System.Data.Linq.DataContext
27 | {
28 |
29 | private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();
30 |
31 | #region Extensibility Method Definitions
32 | partial void OnCreated();
33 | partial void InsertCustomer(Customer instance);
34 | partial void UpdateCustomer(Customer instance);
35 | partial void DeleteCustomer(Customer instance);
36 | #endregion
37 |
38 | public CustomersDataContext() :
39 | base(global::DVFilterSort.Properties.Settings.Default.CustomersConnectionString, mappingSource)
40 | {
41 | OnCreated();
42 | }
43 |
44 | public CustomersDataContext(string connection) :
45 | base(connection, mappingSource)
46 | {
47 | OnCreated();
48 | }
49 |
50 | public CustomersDataContext(System.Data.IDbConnection connection) :
51 | base(connection, mappingSource)
52 | {
53 | OnCreated();
54 | }
55 |
56 | public CustomersDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
57 | base(connection, mappingSource)
58 | {
59 | OnCreated();
60 | }
61 |
62 | public CustomersDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
63 | base(connection, mappingSource)
64 | {
65 | OnCreated();
66 | }
67 |
68 | public System.Data.Linq.Table Customers
69 | {
70 | get
71 | {
72 | return this.GetTable();
73 | }
74 | }
75 |
76 | [global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.GetCount")]
77 | public ISingleResult GetCount([global::System.Data.Linq.Mapping.ParameterAttribute(Name="BeginDate", DbType="DateTime")] System.Nullable beginDate, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="EndDate", DbType="DateTime")] System.Nullable endDate)
78 | {
79 | IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), beginDate, endDate);
80 | return ((ISingleResult)(result.ReturnValue));
81 | }
82 |
83 | [global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.GetSortedFilteredCustomers")]
84 | public ISingleResult GetSortedFilteredCustomers([global::System.Data.Linq.Mapping.ParameterAttribute(Name = "StartIndex", DbType = "Int")] System.Nullable startIndex, [global::System.Data.Linq.Mapping.ParameterAttribute(Name = "EndIndex", DbType = "Int")] System.Nullable endIndex, [global::System.Data.Linq.Mapping.ParameterAttribute(Name = "BeginDate", DbType = "DateTime")] System.Nullable beginDate, [global::System.Data.Linq.Mapping.ParameterAttribute(Name = "EndDate", DbType = "DateTime")] System.Nullable endDate, [global::System.Data.Linq.Mapping.ParameterAttribute(Name = "OrderBy", DbType = "VarChar(500)")] string orderBy)
85 | {
86 | IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), startIndex, endIndex, beginDate, endDate, orderBy);
87 | return ((ISingleResult)(result.ReturnValue));
88 | }
89 | }
90 |
91 | [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Customer")]
92 | public partial class Customer : INotifyPropertyChanging, INotifyPropertyChanged
93 | {
94 |
95 | private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
96 |
97 | private int _Id;
98 |
99 | private string _FirstName;
100 |
101 | private string _LastName;
102 |
103 | private System.DateTime _CustomerSince;
104 |
105 | private double _AmountPaidLocalCalls;
106 |
107 | private double _AmountPaidNationalCalls;
108 |
109 | private double _AmountPaidInternationalCalls;
110 |
111 | private int _NumberFamilyMembersInPlan;
112 |
113 | private bool _JoinedPreferredProgram;
114 |
115 | private int _Region;
116 |
117 | #region Extensibility Method Definitions
118 | partial void OnLoaded();
119 | partial void OnValidate(System.Data.Linq.ChangeAction action);
120 | partial void OnCreated();
121 | partial void OnIdChanging(int value);
122 | partial void OnIdChanged();
123 | partial void OnFirstNameChanging(string value);
124 | partial void OnFirstNameChanged();
125 | partial void OnLastNameChanging(string value);
126 | partial void OnLastNameChanged();
127 | partial void OnCustomerSinceChanging(System.DateTime value);
128 | partial void OnCustomerSinceChanged();
129 | partial void OnAmountPaidLocalCallsChanging(double value);
130 | partial void OnAmountPaidLocalCallsChanged();
131 | partial void OnAmountPaidNationalCallsChanging(double value);
132 | partial void OnAmountPaidNationalCallsChanged();
133 | partial void OnAmountPaidInternationalCallsChanging(double value);
134 | partial void OnAmountPaidInternationalCallsChanged();
135 | partial void OnNumberFamilyMembersInPlanChanging(int value);
136 | partial void OnNumberFamilyMembersInPlanChanged();
137 | partial void OnJoinedPreferredProgramChanging(bool value);
138 | partial void OnJoinedPreferredProgramChanged();
139 | partial void OnRegionChanging(int value);
140 | partial void OnRegionChanged();
141 | #endregion
142 |
143 | public Customer()
144 | {
145 | OnCreated();
146 | }
147 |
148 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
149 | public int Id
150 | {
151 | get
152 | {
153 | return this._Id;
154 | }
155 | set
156 | {
157 | if ((this._Id != value))
158 | {
159 | this.OnIdChanging(value);
160 | this.SendPropertyChanging();
161 | this._Id = value;
162 | this.SendPropertyChanged("Id");
163 | this.OnIdChanged();
164 | }
165 | }
166 | }
167 |
168 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_FirstName", DbType="NVarChar(4000)")]
169 | public string FirstName
170 | {
171 | get
172 | {
173 | return this._FirstName;
174 | }
175 | set
176 | {
177 | if ((this._FirstName != value))
178 | {
179 | this.OnFirstNameChanging(value);
180 | this.SendPropertyChanging();
181 | this._FirstName = value;
182 | this.SendPropertyChanged("FirstName");
183 | this.OnFirstNameChanged();
184 | }
185 | }
186 | }
187 |
188 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_LastName", DbType="NVarChar(4000)")]
189 | public string LastName
190 | {
191 | get
192 | {
193 | return this._LastName;
194 | }
195 | set
196 | {
197 | if ((this._LastName != value))
198 | {
199 | this.OnLastNameChanging(value);
200 | this.SendPropertyChanging();
201 | this._LastName = value;
202 | this.SendPropertyChanged("LastName");
203 | this.OnLastNameChanged();
204 | }
205 | }
206 | }
207 |
208 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_CustomerSince", DbType="DateTime NOT NULL")]
209 | public System.DateTime CustomerSince
210 | {
211 | get
212 | {
213 | return this._CustomerSince;
214 | }
215 | set
216 | {
217 | if ((this._CustomerSince != value))
218 | {
219 | this.OnCustomerSinceChanging(value);
220 | this.SendPropertyChanging();
221 | this._CustomerSince = value;
222 | this.SendPropertyChanged("CustomerSince");
223 | this.OnCustomerSinceChanged();
224 | }
225 | }
226 | }
227 |
228 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_AmountPaidLocalCalls", DbType="Float NOT NULL")]
229 | public double AmountPaidLocalCalls
230 | {
231 | get
232 | {
233 | return this._AmountPaidLocalCalls;
234 | }
235 | set
236 | {
237 | if ((this._AmountPaidLocalCalls != value))
238 | {
239 | this.OnAmountPaidLocalCallsChanging(value);
240 | this.SendPropertyChanging();
241 | this._AmountPaidLocalCalls = value;
242 | this.SendPropertyChanged("AmountPaidLocalCalls");
243 | this.OnAmountPaidLocalCallsChanged();
244 | }
245 | }
246 | }
247 |
248 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_AmountPaidNationalCalls", DbType="Float NOT NULL")]
249 | public double AmountPaidNationalCalls
250 | {
251 | get
252 | {
253 | return this._AmountPaidNationalCalls;
254 | }
255 | set
256 | {
257 | if ((this._AmountPaidNationalCalls != value))
258 | {
259 | this.OnAmountPaidNationalCallsChanging(value);
260 | this.SendPropertyChanging();
261 | this._AmountPaidNationalCalls = value;
262 | this.SendPropertyChanged("AmountPaidNationalCalls");
263 | this.OnAmountPaidNationalCallsChanged();
264 | }
265 | }
266 | }
267 |
268 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_AmountPaidInternationalCalls", DbType="Float NOT NULL")]
269 | public double AmountPaidInternationalCalls
270 | {
271 | get
272 | {
273 | return this._AmountPaidInternationalCalls;
274 | }
275 | set
276 | {
277 | if ((this._AmountPaidInternationalCalls != value))
278 | {
279 | this.OnAmountPaidInternationalCallsChanging(value);
280 | this.SendPropertyChanging();
281 | this._AmountPaidInternationalCalls = value;
282 | this.SendPropertyChanged("AmountPaidInternationalCalls");
283 | this.OnAmountPaidInternationalCallsChanged();
284 | }
285 | }
286 | }
287 |
288 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_NumberFamilyMembersInPlan", DbType="Int NOT NULL")]
289 | public int NumberFamilyMembersInPlan
290 | {
291 | get
292 | {
293 | return this._NumberFamilyMembersInPlan;
294 | }
295 | set
296 | {
297 | if ((this._NumberFamilyMembersInPlan != value))
298 | {
299 | this.OnNumberFamilyMembersInPlanChanging(value);
300 | this.SendPropertyChanging();
301 | this._NumberFamilyMembersInPlan = value;
302 | this.SendPropertyChanged("NumberFamilyMembersInPlan");
303 | this.OnNumberFamilyMembersInPlanChanged();
304 | }
305 | }
306 | }
307 |
308 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_JoinedPreferredProgram", DbType="Bit NOT NULL")]
309 | public bool JoinedPreferredProgram
310 | {
311 | get
312 | {
313 | return this._JoinedPreferredProgram;
314 | }
315 | set
316 | {
317 | if ((this._JoinedPreferredProgram != value))
318 | {
319 | this.OnJoinedPreferredProgramChanging(value);
320 | this.SendPropertyChanging();
321 | this._JoinedPreferredProgram = value;
322 | this.SendPropertyChanged("JoinedPreferredProgram");
323 | this.OnJoinedPreferredProgramChanged();
324 | }
325 | }
326 | }
327 |
328 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Region", DbType="Int NOT NULL")]
329 | public int Region
330 | {
331 | get
332 | {
333 | return this._Region;
334 | }
335 | set
336 | {
337 | if ((this._Region != value))
338 | {
339 | this.OnRegionChanging(value);
340 | this.SendPropertyChanging();
341 | this._Region = value;
342 | this.SendPropertyChanged("Region");
343 | this.OnRegionChanged();
344 | }
345 | }
346 | }
347 |
348 | public event PropertyChangingEventHandler PropertyChanging;
349 |
350 | public event PropertyChangedEventHandler PropertyChanged;
351 |
352 | protected virtual void SendPropertyChanging()
353 | {
354 | if ((this.PropertyChanging != null))
355 | {
356 | this.PropertyChanging(this, emptyChangingEventArgs);
357 | }
358 | }
359 |
360 | protected virtual void SendPropertyChanged(String propertyName)
361 | {
362 | if ((this.PropertyChanged != null))
363 | {
364 | this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
365 | }
366 | }
367 | }
368 |
369 | public partial class GetCountResult
370 | {
371 |
372 | private System.Nullable _Count;
373 |
374 | public GetCountResult()
375 | {
376 | }
377 |
378 | [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Count", DbType="Int")]
379 | public System.Nullable Count
380 | {
381 | get
382 | {
383 | return this._Count;
384 | }
385 | set
386 | {
387 | if ((this._Count != value))
388 | {
389 | this._Count = value;
390 | }
391 | }
392 | }
393 | }
394 | }
395 | #pragma warning restore 1591
396 |
--------------------------------------------------------------------------------
/DVFilterSort/CustomersDataSet.xsc:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DVFilterSort/CustomersDataSet.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | DELETE FROM [dbo].[Customer] WHERE (([Id] = @Original_Id) AND ((@IsNull_FirstName = 1 AND [FirstName] IS NULL) OR ([FirstName] = @Original_FirstName)) AND ((@IsNull_LastName = 1 AND [LastName] IS NULL) OR ([LastName] = @Original_LastName)) AND ([CustomerSince] = @Original_CustomerSince) AND ([AmountPaidLocalCalls] = @Original_AmountPaidLocalCalls) AND ([AmountPaidNationalCalls] = @Original_AmountPaidNationalCalls) AND ([AmountPaidInternationalCalls] = @Original_AmountPaidInternationalCalls) AND ([NumberFamilyMembersInPlan] = @Original_NumberFamilyMembersInPlan) AND ([JoinedPreferredProgram] = @Original_JoinedPreferredProgram) AND ([Region] = @Original_Region))
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | INSERT INTO [dbo].[Customer] ([FirstName], [LastName], [CustomerSince], [AmountPaidLocalCalls], [AmountPaidNationalCalls], [AmountPaidInternationalCalls], [NumberFamilyMembersInPlan], [JoinedPreferredProgram], [Region]) VALUES (@FirstName, @LastName, @CustomerSince, @AmountPaidLocalCalls, @AmountPaidNationalCalls, @AmountPaidInternationalCalls, @NumberFamilyMembersInPlan, @JoinedPreferredProgram, @Region);
35 | SELECT Id, FirstName, LastName, CustomerSince, AmountPaidLocalCalls, AmountPaidNationalCalls, AmountPaidInternationalCalls, NumberFamilyMembersInPlan, JoinedPreferredProgram, Region FROM Customer WHERE (Id = SCOPE_IDENTITY())
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | SELECT Id, FirstName, LastName, CustomerSince, AmountPaidLocalCalls, AmountPaidNationalCalls, AmountPaidInternationalCalls, NumberFamilyMembersInPlan, JoinedPreferredProgram, Region FROM dbo.Customer
52 |
53 |
54 |
55 |
56 |
57 | UPDATE [dbo].[Customer] SET [FirstName] = @FirstName, [LastName] = @LastName, [CustomerSince] = @CustomerSince, [AmountPaidLocalCalls] = @AmountPaidLocalCalls, [AmountPaidNationalCalls] = @AmountPaidNationalCalls, [AmountPaidInternationalCalls] = @AmountPaidInternationalCalls, [NumberFamilyMembersInPlan] = @NumberFamilyMembersInPlan, [JoinedPreferredProgram] = @JoinedPreferredProgram, [Region] = @Region WHERE (([Id] = @Original_Id) AND ((@IsNull_FirstName = 1 AND [FirstName] IS NULL) OR ([FirstName] = @Original_FirstName)) AND ((@IsNull_LastName = 1 AND [LastName] IS NULL) OR ([LastName] = @Original_LastName)) AND ([CustomerSince] = @Original_CustomerSince) AND ([AmountPaidLocalCalls] = @Original_AmountPaidLocalCalls) AND ([AmountPaidNationalCalls] = @Original_AmountPaidNationalCalls) AND ([AmountPaidInternationalCalls] = @Original_AmountPaidInternationalCalls) AND ([NumberFamilyMembersInPlan] = @Original_NumberFamilyMembersInPlan) AND ([JoinedPreferredProgram] = @Original_JoinedPreferredProgram) AND ([Region] = @Original_Region));
58 | SELECT Id, FirstName, LastName, CustomerSince, AmountPaidLocalCalls, AmountPaidNationalCalls, AmountPaidInternationalCalls, NumberFamilyMembersInPlan, JoinedPreferredProgram, Region FROM Customer WHERE (Id = @Id)
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | dbo.GetCount
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | dbo.GetSortedFilteredCustomers
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/DVFilterSort/CustomersDataSet.xss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DVFilterSort/DVFilterSort.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {EB70E3BF-29CE-40C4-A8B6-EBAB16DECD8A}
9 | WinExe
10 | Properties
11 | DVFilterSort
12 | DVFilterSort
13 | v4.0
14 | Client
15 | 512
16 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
17 | 4
18 |
19 |
20 | x86
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 |
29 |
30 | x86
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | 4.0
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | MSBuild:Compile
58 | Designer
59 |
60 |
61 |
62 |
63 | MSBuild:Compile
64 | Designer
65 |
66 |
67 | App.xaml
68 | Code
69 |
70 |
71 |
72 | True
73 | True
74 | Customers.dbml
75 |
76 |
77 | True
78 | True
79 | CustomersDataSet.xsd
80 |
81 |
82 | MainWindow.xaml
83 | Code
84 |
85 |
86 |
87 |
88 | Code
89 |
90 |
91 | True
92 | True
93 | Resources.resx
94 |
95 |
96 | True
97 | Settings.settings
98 | True
99 |
100 |
101 |
102 | Customers.dbml
103 |
104 |
105 | ResXFileCodeGenerator
106 | Resources.Designer.cs
107 |
108 |
109 | MSLinqToSQLGenerator
110 | Customers.designer.cs
111 | Designer
112 |
113 |
114 | CustomersDataSet.xsd
115 |
116 |
117 | MSDataSetGenerator
118 | CustomersDataSet.Designer.cs
119 | Designer
120 |
121 |
122 | CustomersDataSet.xsd
123 |
124 |
125 | SettingsSingleFileGenerator
126 | Settings.Designer.cs
127 |
128 |
129 |
130 |
131 |
132 | {F0551328-4699-43B6-949E-9BDABF89FC1E}
133 | DataVirtualization
134 |
135 |
136 | {37EC527A-D370-4643-A4A5-F585D18244D1}
137 | ReusableControls
138 |
139 |
140 |
141 |
142 |
143 |
144 |
151 |
--------------------------------------------------------------------------------
/DVFilterSort/DataGridHelper.cs:
--------------------------------------------------------------------------------
1 | #region
2 |
3 | using System.Windows.Controls;
4 | using System.Windows.Data;
5 |
6 | #endregion
7 |
8 | namespace DVFilterSort
9 | {
10 | public static class DataGridHelper
11 | {
12 | public static string GetSortMemberPath(DataGridColumn column)
13 | {
14 | string sortPropertyName = column.SortMemberPath;
15 | if (string.IsNullOrEmpty(sortPropertyName))
16 | {
17 | var boundColumn = column as DataGridBoundColumn;
18 | if (boundColumn != null)
19 | {
20 | var binding = boundColumn.Binding as Binding;
21 | if (binding != null)
22 | {
23 | if (!string.IsNullOrEmpty(binding.XPath))
24 | {
25 | sortPropertyName = binding.XPath;
26 | }
27 | else if (binding.Path != null)
28 | {
29 | sortPropertyName = binding.Path.Path;
30 | }
31 | }
32 | }
33 | }
34 |
35 | return sortPropertyName;
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/DVFilterSort/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
116 |
117 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
195 |
196 |
197 |
198 |
213 |
214 |
217 |
220 |
223 |
226 |
229 |
232 |
235 |
238 |
241 |
242 |
243 |
244 |
245 |
--------------------------------------------------------------------------------
/DVFilterSort/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | #region
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Diagnostics;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Windows;
10 | using System.Windows.Controls;
11 | using System.Windows.Input;
12 | using DataVirtualization;
13 |
14 | #endregion
15 |
16 | namespace DVFilterSort
17 | {
18 | ///
19 | /// Interaction logic for MainWindow.xaml
20 | ///
21 | public partial class MainWindow : Window
22 | {
23 | private readonly List sortDescriptions;
24 | private CustomerProvider customerProvider;
25 | private int pageSize = 100;
26 | private int timePageInMemory = 5000;
27 |
28 | public MainWindow()
29 | {
30 | PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Off;
31 |
32 | InitializeComponent();
33 |
34 | string defaultSortColumnName = "CustomerSince";
35 | DataGridColumn defaultSortColumn = CustomersDataGrid.Columns.Single(dgc => GetColumnSortMemberPath(dgc) == defaultSortColumnName);
36 | sortDescriptions = new List
37 | {
38 | new CustomSortDescription
39 | {
40 | PropertyName = defaultSortColumnName,
41 | Direction = ListSortDirection.Descending,
42 | Column = defaultSortColumn
43 | }
44 | };
45 | RefreshData();
46 | }
47 |
48 | private void CustomerSinceDatePicker_DateChanged(object sender, EventArgs e)
49 | {
50 | RefreshData();
51 | }
52 |
53 | private void Customers_Sorting(object sender, DataGridSortingEventArgs e)
54 | {
55 | ApplySortColumn(e.Column);
56 | e.Handled = true;
57 | }
58 |
59 | private void RefreshData()
60 | {
61 | string sortString = GetCurrentSortString();
62 | customerProvider = new CustomerProvider(CustomerSinceDatePicker.DateFrom, CustomerSinceDatePicker.DateTo, sortString);
63 | var customerList = new AsyncVirtualizingCollection(customerProvider, pageSize, timePageInMemory);
64 | DataContext = customerList;
65 |
66 | UpdateSortingVisualFeedback();
67 |
68 | CustomersDataGrid.SelectedIndex = 0;
69 | }
70 |
71 | private void ApplySortColumn(DataGridColumn column)
72 | {
73 | // If column was not sorted, we sort it ascending. If it was already sorted, we flip the sort direction.
74 | string sortColumn = GetColumnSortMemberPath(column);
75 | CustomSortDescription existingSortDescription = sortDescriptions.SingleOrDefault(sd => sd.PropertyName == sortColumn);
76 | if (existingSortDescription == null)
77 | {
78 | existingSortDescription = new CustomSortDescription
79 | {
80 | PropertyName = sortColumn,
81 | Direction = ListSortDirection.Ascending,
82 | Column = column
83 | };
84 | sortDescriptions.Add(existingSortDescription);
85 | }
86 | else
87 | {
88 | existingSortDescription.Direction = (existingSortDescription.Direction == ListSortDirection.Ascending) ? ListSortDirection.Descending : ListSortDirection.Ascending;
89 | }
90 |
91 | // If user is not pressing Shift, we remove all SortDescriptions except the current one.
92 | bool isShiftPressed = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
93 | if (!isShiftPressed)
94 | {
95 | for (int i = sortDescriptions.Count - 1; i >= 0; i--)
96 | {
97 | CustomSortDescription csd = sortDescriptions[i];
98 | if (csd.PropertyName != sortColumn)
99 | {
100 | sortDescriptions.RemoveAt(i);
101 | }
102 | }
103 | }
104 |
105 | RefreshData();
106 | }
107 |
108 | private string GetColumnSortMemberPath(DataGridColumn column)
109 | {
110 | string prefixToRemove = "Data.";
111 | string fullSortColumn = DataGridHelper.GetSortMemberPath(column);
112 | string sortColumn = fullSortColumn.Substring(prefixToRemove.Length);
113 | return sortColumn;
114 | }
115 |
116 | private string GetCurrentSortString()
117 | {
118 | // The result string is created, taking into account all sorted columns in the order they were sorted.
119 | var result = new StringBuilder();
120 | string separator = String.Empty;
121 | foreach (CustomSortDescription sd in sortDescriptions)
122 | {
123 | result.Append(separator);
124 | result.Append(sd.PropertyName);
125 | if (sd.Direction == ListSortDirection.Descending)
126 | {
127 | result = result.Append(" DESC");
128 | }
129 | separator = ", ";
130 | }
131 |
132 | return result.ToString();
133 | }
134 |
135 | private void UpdateSortingVisualFeedback()
136 | {
137 | foreach (CustomSortDescription csd in sortDescriptions)
138 | {
139 | csd.Column.SortDirection = csd.Direction;
140 | }
141 | }
142 | }
143 |
144 | public class CustomSortDescription
145 | {
146 | public string PropertyName { get; set; }
147 | public ListSortDirection Direction { get; set; }
148 | public DataGridColumn Column { get; set; }
149 | }
150 |
151 | public enum USRegion
152 | {
153 | Northeast,
154 | Southeast,
155 | Midwest,
156 | Southwest,
157 | West
158 | }
159 | }
--------------------------------------------------------------------------------
/DVFilterSort/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("DVFilterSort")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("Microsoft")]
14 | [assembly: AssemblyProduct("DVFilterSort")]
15 | [assembly: AssemblyCopyright("Copyright © Microsoft 2009")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/DVFilterSort/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.21006.1
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DVFilterSort.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DVFilterSort.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/DVFilterSort/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/DVFilterSort/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.21006.1
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DVFilterSort.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
29 | [global::System.Configuration.DefaultSettingValueAttribute("Data Source=STOLLNITZ-GREEN\\SQLEXPRESS;Initial Catalog=Customers;Integrated Secur" +
30 | "ity=True")]
31 | public string CustomersConnectionString {
32 | get {
33 | return ((string)(this["CustomersConnectionString"]));
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/DVFilterSort/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | <?xml version="1.0" encoding="utf-16"?>
7 | <SerializableConnectionString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
8 | <ConnectionString>Data Source=STOLLNITZ-GREEN\SQLEXPRESS;Initial Catalog=Customers;Integrated Security=True</ConnectionString>
9 | <ProviderName>System.Data.SqlClient</ProviderName>
10 | </SerializableConnectionString>
11 | Data Source=STOLLNITZ-GREEN\SQLEXPRESS;Initial Catalog=Customers;Integrated Security=True
12 |
13 |
14 |
--------------------------------------------------------------------------------
/DVFilterSort/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/DataVirtualization/AsyncVirtualizingCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Collections.Specialized;
6 | using System.ComponentModel;
7 | using System.Threading;
8 | using System.Collections;
9 |
10 | namespace DataVirtualization
11 | {
12 | ///
13 | /// Derived VirtualizatingCollection, performing loading asychronously.
14 | ///
15 | /// The type of items in the collection
16 | public class AsyncVirtualizingCollection : VirtualizingCollection, INotifyCollectionChanged, INotifyPropertyChanged where T : class
17 | {
18 | ///
19 | /// Initializes a new instance of the class.
20 | ///
21 | /// The items provider.
22 | /// Size of the page.
23 | /// The page timeout.
24 | public AsyncVirtualizingCollection(IItemsProvider itemsProvider, int pageSize, int pageTimeout)
25 | : base(itemsProvider, pageSize, pageTimeout)
26 | {
27 | _synchronizationContext = SynchronizationContext.Current;
28 | }
29 |
30 | #region SynchronizationContext
31 |
32 | private readonly SynchronizationContext _synchronizationContext;
33 |
34 | ///
35 | /// Gets the synchronization context used for UI-related operations. This is obtained as
36 | /// the current SynchronizationContext when the AsyncVirtualizingCollection is created.
37 | ///
38 | /// The synchronization context.
39 | protected SynchronizationContext SynchronizationContext
40 | {
41 | get { return _synchronizationContext; }
42 | }
43 |
44 | #endregion
45 |
46 | #region INotifyCollectionChanged
47 |
48 | ///
49 | /// Occurs when the collection changes.
50 | ///
51 | public event NotifyCollectionChangedEventHandler CollectionChanged;
52 |
53 | ///
54 | /// Raises the event.
55 | ///
56 | /// The instance containing the event data.
57 | protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
58 | {
59 | NotifyCollectionChangedEventHandler h = CollectionChanged;
60 | if (h != null)
61 | h(this, e);
62 | }
63 |
64 | ///
65 | /// Fires the collection reset event.
66 | ///
67 | private void FireCollectionReset()
68 | {
69 | NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
70 | OnCollectionChanged(e);
71 | }
72 |
73 | #endregion
74 |
75 | #region INotifyPropertyChanged
76 |
77 | ///
78 | /// Occurs when a property value changes.
79 | ///
80 | public event PropertyChangedEventHandler PropertyChanged;
81 |
82 | ///
83 | /// Raises the event.
84 | ///
85 | /// The instance containing the event data.
86 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
87 | {
88 | PropertyChangedEventHandler h = PropertyChanged;
89 | if (h != null)
90 | h(this, e);
91 | }
92 |
93 | ///
94 | /// Fires the property changed event.
95 | ///
96 | /// Name of the property.
97 | private void FirePropertyChanged(string propertyName)
98 | {
99 | PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
100 | OnPropertyChanged(e);
101 | }
102 |
103 | #endregion
104 |
105 | #region IsLoading
106 |
107 | private bool _isLoading;
108 |
109 | ///
110 | /// Gets or sets a value indicating whether the collection is loading.
111 | ///
112 | ///
113 | /// true if this collection is loading; otherwise, false.
114 | ///
115 | public bool IsLoading
116 | {
117 | get
118 | {
119 | return _isLoading;
120 | }
121 | set
122 | {
123 | if (value != _isLoading)
124 | {
125 | _isLoading = value;
126 | FirePropertyChanged("IsLoading");
127 | }
128 | }
129 | }
130 |
131 | private bool _isInitializing;
132 |
133 | public bool IsInitializing
134 | {
135 | get
136 | {
137 | return _isInitializing;
138 | }
139 | set
140 | {
141 | if (value != _isInitializing)
142 | {
143 | _isInitializing = value;
144 | FirePropertyChanged("IsInitializing");
145 | }
146 | }
147 | }
148 | #endregion
149 |
150 | #region Load overrides
151 |
152 | ///
153 | /// Asynchronously loads the count of items.
154 | ///
155 | protected override void LoadCount()
156 | {
157 | if (Count == 0)
158 | {
159 | IsInitializing = true;
160 | }
161 | ThreadPool.QueueUserWorkItem(LoadCountWork);
162 | }
163 |
164 | ///
165 | /// Performed on background thread.
166 | ///
167 | /// None required.
168 | private void LoadCountWork(object args)
169 | {
170 | int count = FetchCount();
171 | SynchronizationContext.Send(LoadCountCompleted, count);
172 | }
173 |
174 | ///
175 | /// Performed on UI-thread after LoadCountWork.
176 | ///
177 | /// Number of items returned.
178 | protected virtual void LoadCountCompleted(object args)
179 | {
180 | int newCount = (int)args;
181 | this.TakeNewCount(newCount);
182 | IsInitializing = false;
183 | }
184 |
185 | private void TakeNewCount(int newCount)
186 | {
187 | if (newCount != this.Count)
188 | {
189 | this.Count = newCount;
190 | this.EmptyCache();
191 | FireCollectionReset();
192 | }
193 | }
194 |
195 | ///
196 | /// Asynchronously loads the page.
197 | ///
198 | /// The index.
199 | protected override void LoadPage(int pageIndex, int pageLength)
200 | {
201 | IsLoading = true;
202 | ThreadPool.QueueUserWorkItem(LoadPageWork, new int[] { pageIndex, pageLength });
203 | }
204 |
205 | ///
206 | /// Performed on background thread.
207 | ///
208 | /// Index of the page to load.
209 | private void LoadPageWork(object state)
210 | {
211 | int[] args = (int[])state;
212 | int pageIndex = args[0];
213 | int pageLength = args[1];
214 | int overallCount = 0;
215 | IList dataItems = FetchPage(pageIndex, pageLength, out overallCount);
216 | SynchronizationContext.Send(LoadPageCompleted, new object[] { pageIndex, dataItems, overallCount });
217 | }
218 |
219 | ///
220 | /// Performed on UI-thread after LoadPageWork.
221 | ///
222 | /// object[] { int pageIndex, IList(T) page }
223 | private void LoadPageCompleted(object state)
224 | {
225 | object[] args = (object[])state;
226 | int pageIndex = (int)args[0];
227 | IList dataItems = (IList)args[1];
228 | int newCount = (int)args[2];
229 | this.TakeNewCount(newCount);
230 |
231 | PopulatePage(pageIndex, dataItems);
232 | IsLoading = false;
233 | }
234 |
235 | #endregion
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/DataVirtualization/DataPage.cs:
--------------------------------------------------------------------------------
1 | #region
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | #endregion
8 |
9 | namespace DataVirtualization
10 | {
11 | public class DataPage where T : class
12 | {
13 | public DataPage(int firstIndex, int pageLength)
14 | {
15 | Items = new List>(pageLength);
16 | for (int i = 0; i < pageLength; i++)
17 | {
18 | Items.Add(new DataWrapper(firstIndex + i));
19 | }
20 | TouchTime = DateTime.Now;
21 | }
22 |
23 | public IList> Items { get; private set; }
24 |
25 | public DateTime TouchTime { get; set; }
26 |
27 | public bool IsInUse
28 | {
29 | get { return Items.Any(wrapper => wrapper.IsInUse); }
30 | }
31 |
32 | public void Populate(IList newItems)
33 | {
34 | int i;
35 | int index = 0;
36 | for (i = 0; i < newItems.Count && i < Items.Count; i++)
37 | {
38 | Items[i].Data = newItems[i];
39 | index = Items[i].Index;
40 | }
41 |
42 | while (i < newItems.Count)
43 | {
44 | index++;
45 | Items.Add(new DataWrapper(index) {Data = newItems[i]});
46 | i++;
47 | }
48 |
49 | while (i < Items.Count)
50 | {
51 | Items.RemoveAt(Items.Count - 1);
52 | }
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/DataVirtualization/DataVirtualization.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {F0551328-4699-43B6-949E-9BDABF89FC1E}
9 | Library
10 | Properties
11 | DataVirtualization
12 | DataVirtualization
13 | v4.0
14 | 512
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
58 |
--------------------------------------------------------------------------------
/DataVirtualization/DataWrapper.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace DataVirtualization
4 | {
5 | public class DataWrapper : INotifyPropertyChanged where T : class
6 | {
7 | private int index;
8 | private T data;
9 |
10 | public event PropertyChangedEventHandler PropertyChanged;
11 |
12 | public DataWrapper(int index)
13 | {
14 | this.index = index;
15 | }
16 |
17 | public int Index
18 | {
19 | get { return this.index; }
20 | }
21 |
22 | public int ItemNumber
23 | {
24 | get { return this.index + 1; }
25 | }
26 |
27 | public bool IsLoading
28 | {
29 | get { return this.Data == null; }
30 | }
31 |
32 | public T Data
33 | {
34 | get { return this.data; }
35 | internal set
36 | {
37 | this.data = value;
38 | this.OnPropertyChanged("Data");
39 | this.OnPropertyChanged("IsLoading");
40 | }
41 | }
42 |
43 | public bool IsInUse
44 | {
45 | get { return this.PropertyChanged != null; }
46 | }
47 |
48 | private void OnPropertyChanged(string propertyName)
49 | {
50 | System.Diagnostics.Debug.Assert(this.GetType().GetProperty(propertyName) != null);
51 | var handler = this.PropertyChanged;
52 | if (handler != null)
53 | {
54 | handler(this, new PropertyChangedEventArgs(propertyName));
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/DataVirtualization/IItemsProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace DataVirtualization
7 | {
8 | ///
9 | /// Represents a provider of collection details.
10 | ///
11 | /// The type of items in the collection.
12 | public interface IItemsProvider
13 | {
14 | ///
15 | /// Fetches the total number of items available.
16 | ///
17 | ///
18 | int FetchCount();
19 |
20 | ///
21 | /// Fetches a range of items.
22 | ///
23 | /// The start index.
24 | /// The number of items to fetch.
25 | ///
26 | IList FetchRange(int startIndex, int pageCount, out int overallCount);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/DataVirtualization/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("DataVirtualization")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("DataVirtualization")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2009")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("5c878b02-f171-4afd-aa12-94cbdac79742")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/DataVirtualization/VirtualizingCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Collections;
6 | using System.Diagnostics;
7 | using System.ComponentModel;
8 |
9 | namespace DataVirtualization
10 | {
11 | ///
12 | /// Specialized list implementation that provides data virtualization. The collection is divided up into pages,
13 | /// and pages are dynamically fetched from the IItemsProvider when required. Stale pages are removed after a
14 | /// configurable period of time.
15 | /// Intended for use with large collections on a network or disk resource that cannot be instantiated locally
16 | /// due to memory consumption or fetch latency.
17 | ///
18 | ///
19 | /// The IList implmentation is not fully complete, but should be sufficient for use as read only collection
20 | /// data bound to a suitable ItemsControl.
21 | ///
22 | ///
23 | public class VirtualizingCollection : IList>, IList where T : class
24 | {
25 | #region Constructors
26 |
27 | ///
28 | /// Initializes a new instance of the class.
29 | ///
30 | /// The items provider.
31 | /// Size of the page.
32 | /// The page timeout.
33 | public VirtualizingCollection(IItemsProvider itemsProvider, int pageSize, int pageTimeout)
34 | {
35 | _itemsProvider = itemsProvider;
36 | _pageSize = pageSize;
37 | _pageTimeout = pageTimeout;
38 | }
39 |
40 | ///
41 | /// Initializes a new instance of the class.
42 | ///
43 | /// The items provider.
44 | /// Size of the page.
45 | public VirtualizingCollection(IItemsProvider itemsProvider, int pageSize)
46 | {
47 | _itemsProvider = itemsProvider;
48 | _pageSize = pageSize;
49 | }
50 |
51 | ///
52 | /// Initializes a new instance of the class.
53 | ///
54 | /// The items provider.
55 | public VirtualizingCollection(IItemsProvider itemsProvider)
56 | {
57 | _itemsProvider = itemsProvider;
58 | }
59 |
60 | #endregion
61 |
62 | #region ItemsProvider
63 |
64 | private readonly IItemsProvider _itemsProvider;
65 |
66 | ///
67 | /// Gets the items provider.
68 | ///
69 | /// The items provider.
70 | public IItemsProvider ItemsProvider
71 | {
72 | get { return _itemsProvider; }
73 | }
74 |
75 | #endregion
76 |
77 | #region PageSize
78 |
79 | private readonly int _pageSize = 100;
80 |
81 | ///
82 | /// Gets the size of the page.
83 | ///
84 | /// The size of the page.
85 | public int PageSize
86 | {
87 | get { return _pageSize; }
88 | }
89 |
90 | #endregion
91 |
92 | #region PageTimeout
93 |
94 | private readonly long _pageTimeout = 10000;
95 |
96 | ///
97 | /// Gets the page timeout.
98 | ///
99 | /// The page timeout.
100 | public long PageTimeout
101 | {
102 | get { return _pageTimeout; }
103 | }
104 |
105 | #endregion
106 |
107 | #region IList>, IList
108 |
109 | #region Count
110 |
111 | private int _count = -1;
112 |
113 | ///
114 | /// Gets the number of elements contained in the .
115 | /// The first time this property is accessed, it will fetch the count from the IItemsProvider.
116 | ///
117 | ///
118 | ///
119 | /// The number of elements contained in the .
120 | ///
121 | public int Count
122 | {
123 | get
124 | {
125 | if (_count == -1)
126 | {
127 | _count = 0;
128 | LoadCount();
129 | }
130 | return _count;
131 | }
132 | protected set
133 | {
134 | _count = value;
135 | }
136 | }
137 |
138 | #endregion
139 |
140 | #region Indexer
141 |
142 | ///
143 | /// Gets the item at the specified index. This property will fetch
144 | /// the corresponding page from the IItemsProvider if required.
145 | ///
146 | ///
147 | public DataWrapper this[int index]
148 | {
149 | get
150 | {
151 | // determine which page and offset within page
152 | int pageIndex = index / PageSize;
153 | int pageOffset = index % PageSize;
154 |
155 | // request primary page
156 | RequestPage(pageIndex);
157 |
158 | // if accessing upper 50% then request next page
159 | if (pageOffset > PageSize / 2 && pageIndex < Count / PageSize)
160 | RequestPage(pageIndex + 1);
161 |
162 | // if accessing lower 50% then request prev page
163 | if (pageOffset < PageSize / 2 && pageIndex > 0)
164 | RequestPage(pageIndex - 1);
165 |
166 | // remove stale pages
167 | CleanUpPages();
168 |
169 | // return requested item
170 | return _pages[pageIndex].Items[pageOffset];
171 | }
172 | set { throw new NotSupportedException(); }
173 | }
174 |
175 | object IList.this[int index]
176 | {
177 | get { return this[index]; }
178 | set { throw new NotSupportedException(); }
179 | }
180 |
181 | #endregion
182 |
183 | #region IEnumerator>, IEnumerator
184 |
185 | ///
186 | /// Returns an enumerator that iterates through the collection.
187 | ///
188 | ///
189 | /// This method should be avoided on large collections due to poor performance.
190 | ///
191 | ///
192 | /// A that can be used to iterate through the collection.
193 | ///
194 | public IEnumerator> GetEnumerator()
195 | {
196 | for (int i = 0; i < Count; i++)
197 | {
198 | yield return this[i];
199 | }
200 | }
201 |
202 | ///
203 | /// Returns an enumerator that iterates through a collection.
204 | ///
205 | ///
206 | /// An object that can be used to iterate through the collection.
207 | ///
208 | IEnumerator IEnumerable.GetEnumerator()
209 | {
210 | return GetEnumerator();
211 | }
212 |
213 | #endregion
214 |
215 | #region Add
216 |
217 | ///
218 | /// Not supported.
219 | ///
220 | /// The object to add to the .
221 | ///
222 | /// The is read-only.
223 | ///
224 | public void Add(DataWrapper item)
225 | {
226 | throw new NotSupportedException();
227 | }
228 |
229 | int IList.Add(object value)
230 | {
231 | throw new NotSupportedException();
232 | }
233 |
234 | #endregion
235 |
236 | #region Contains
237 |
238 | bool IList.Contains(object value)
239 | {
240 | return Contains((DataWrapper)value);
241 | }
242 |
243 | ///
244 | /// Not supported.
245 | ///
246 | /// The object to locate in the .
247 | ///
248 | /// Always false.
249 | ///
250 | public bool Contains(DataWrapper item)
251 | {
252 | foreach (DataPage page in _pages.Values)
253 | {
254 | if (page.Items.Contains(item))
255 | {
256 | return true;
257 | }
258 | }
259 | return false;
260 | }
261 |
262 | #endregion
263 |
264 | #region Clear
265 |
266 | ///
267 | /// TODO
268 | ///
269 | public void Clear()
270 | {
271 | throw new NotSupportedException();
272 | }
273 |
274 | #endregion
275 |
276 | #region IndexOf
277 |
278 | int IList.IndexOf(object value)
279 | {
280 | return IndexOf((DataWrapper)value);
281 | }
282 |
283 | ///
284 | /// TODO
285 | ///
286 | /// The object to locate in the .
287 | ///
288 | /// TODO
289 | ///
290 | public int IndexOf(DataWrapper item)
291 | {
292 | foreach (KeyValuePair> keyValuePair in _pages)
293 | {
294 | int indexWithinPage = keyValuePair.Value.Items.IndexOf(item);
295 | if (indexWithinPage != -1)
296 | {
297 | return PageSize * keyValuePair.Key + indexWithinPage;
298 | }
299 | }
300 | return -1;
301 | }
302 |
303 | #endregion
304 |
305 | #region Insert
306 |
307 | ///
308 | /// Not supported.
309 | ///
310 | /// The zero-based index at which should be inserted.
311 | /// The object to insert into the .
312 | ///
313 | /// is not a valid index in the .
314 | ///
315 | ///
316 | /// The is read-only.
317 | ///
318 | public void Insert(int index, DataWrapper item)
319 | {
320 | throw new NotSupportedException();
321 | }
322 |
323 | void IList.Insert(int index, object value)
324 | {
325 | Insert(index, (DataWrapper)value);
326 | }
327 |
328 | #endregion
329 |
330 | #region Remove
331 |
332 | ///
333 | /// Not supported.
334 | ///
335 | /// The zero-based index of the item to remove.
336 | ///
337 | /// is not a valid index in the .
338 | ///
339 | ///
340 | /// The is read-only.
341 | ///
342 | public void RemoveAt(int index)
343 | {
344 | throw new NotSupportedException();
345 | }
346 |
347 | void IList.Remove(object value)
348 | {
349 | throw new NotSupportedException();
350 | }
351 |
352 | ///
353 | /// Not supported.
354 | ///
355 | /// The object to remove from the .
356 | ///
357 | /// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
358 | ///
359 | ///
360 | /// The is read-only.
361 | ///
362 | public bool Remove(DataWrapper item)
363 | {
364 | throw new NotSupportedException();
365 | }
366 |
367 | #endregion
368 |
369 | #region CopyTo
370 |
371 | ///
372 | /// Not supported.
373 | ///
374 | /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing.
375 | /// The zero-based index in at which copying begins.
376 | ///
377 | /// is null.
378 | ///
379 | ///
380 | /// is less than 0.
381 | ///
382 | ///
383 | /// is multidimensional.
384 | /// -or-
385 | /// is equal to or greater than the length of .
386 | /// -or-
387 | /// The number of elements in the source is greater than the available space from to the end of the destination .
388 | /// -or-
389 | /// Type cannot be cast automatically to the type of the destination .
390 | ///
391 | public void CopyTo(DataWrapper[] array, int arrayIndex)
392 | {
393 | throw new NotSupportedException();
394 | }
395 |
396 | void ICollection.CopyTo(Array array, int index)
397 | {
398 | throw new NotSupportedException();
399 | }
400 |
401 | #endregion
402 |
403 | #region Misc
404 |
405 | ///
406 | /// Gets an object that can be used to synchronize access to the .
407 | ///
408 | ///
409 | ///
410 | /// An object that can be used to synchronize access to the .
411 | ///
412 | public object SyncRoot
413 | {
414 | get { return this; }
415 | }
416 |
417 | ///
418 | /// Gets a value indicating whether access to the is synchronized (thread safe).
419 | ///
420 | ///
421 | /// Always false.
422 | ///
423 | public bool IsSynchronized
424 | {
425 | get { return false; }
426 | }
427 |
428 | ///
429 | /// Gets a value indicating whether the is read-only.
430 | ///
431 | ///
432 | /// Always true.
433 | ///
434 | public bool IsReadOnly
435 | {
436 | get { return true; }
437 | }
438 |
439 | ///
440 | /// Gets a value indicating whether the has a fixed size.
441 | ///
442 | ///
443 | /// Always false.
444 | ///
445 | public bool IsFixedSize
446 | {
447 | get { return false; }
448 | }
449 |
450 | #endregion
451 |
452 | #endregion
453 |
454 | #region Paging
455 |
456 | private Dictionary> _pages = new Dictionary>();
457 |
458 | ///
459 | /// Cleans up any stale pages that have not been accessed in the period dictated by PageTimeout.
460 | ///
461 | public void CleanUpPages()
462 | {
463 | int[] keys = _pages.Keys.ToArray();
464 | foreach (int key in keys)
465 | {
466 | // page 0 is a special case, since WPF ItemsControl access the first item frequently
467 | if (key != 0 && (DateTime.Now - _pages[key].TouchTime).TotalMilliseconds > PageTimeout)
468 | {
469 | bool removePage = true;
470 | DataPage page;
471 | if (_pages.TryGetValue(key, out page))
472 | {
473 | removePage = !page.IsInUse;
474 | }
475 |
476 | if (removePage)
477 | {
478 | _pages.Remove(key);
479 | Trace.WriteLine("Removed Page: " + key);
480 | }
481 | }
482 | }
483 | }
484 |
485 | ///
486 | /// Makes a request for the specified page, creating the necessary slots in the dictionary,
487 | /// and updating the page touch time.
488 | ///
489 | /// Index of the page.
490 | protected virtual void RequestPage(int pageIndex)
491 | {
492 | if (!_pages.ContainsKey(pageIndex))
493 | {
494 | // Create a page of empty data wrappers.
495 | int pageLength = Math.Min(this.PageSize, this.Count - pageIndex * this.PageSize);
496 | DataPage page = new DataPage(pageIndex * this.PageSize, pageLength);
497 | _pages.Add(pageIndex, page);
498 | Trace.WriteLine("Added page: " + pageIndex);
499 | LoadPage(pageIndex, pageLength);
500 | }
501 | else
502 | {
503 | _pages[pageIndex].TouchTime = DateTime.Now;
504 | }
505 | }
506 |
507 | ///
508 | /// Populates the page within the dictionary.
509 | ///
510 | /// Index of the page.
511 | /// The page.
512 | protected virtual void PopulatePage(int pageIndex, IList dataItems)
513 | {
514 | Trace.WriteLine("Page populated: " + pageIndex);
515 | DataPage page;
516 | if (_pages.TryGetValue(pageIndex, out page))
517 | {
518 | page.Populate(dataItems);
519 | }
520 | }
521 |
522 | ///
523 | /// Removes all cached pages. This is useful when the count of the
524 | /// underlying collection changes.
525 | ///
526 | protected void EmptyCache()
527 | {
528 | _pages = new Dictionary>();
529 | }
530 |
531 | #endregion
532 |
533 | #region Load methods
534 |
535 | ///
536 | /// Loads the count of items.
537 | ///
538 | protected virtual void LoadCount()
539 | {
540 | this.Count = FetchCount();
541 | }
542 |
543 | ///
544 | /// Loads the page of items.
545 | ///
546 | /// Index of the page.
547 | /// Number of items in the page.
548 | protected virtual void LoadPage(int pageIndex, int pageLength)
549 | {
550 | int count = 0;
551 | PopulatePage(pageIndex, FetchPage(pageIndex, pageLength, out count));
552 | this.Count = count;
553 | }
554 |
555 | #endregion
556 |
557 | #region Fetch methods
558 |
559 | ///
560 | /// Fetches the requested page from the IItemsProvider.
561 | ///
562 | /// Index of the page.
563 | ///
564 | protected IList FetchPage(int pageIndex, int pageLength, out int count)
565 | {
566 | return ItemsProvider.FetchRange(pageIndex * PageSize, pageLength, out count);
567 | }
568 |
569 | ///
570 | /// Fetches the count of itmes from the IItemsProvider.
571 | ///
572 | ///
573 | protected int FetchCount()
574 | {
575 | return ItemsProvider.FetchCount();
576 | }
577 |
578 | #endregion
579 | }
580 | }
581 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Virtualization
2 | ==============
3 |
4 | Data virtualization in WPF, UI virtualization
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
7 | files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
8 | modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
12 | Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
15 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
--------------------------------------------------------------------------------
/ReusableControls/DateRangePicker.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/ReusableControls/DateRangePicker.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Navigation;
13 | using System.Windows.Shapes;
14 |
15 | namespace ReusableControls
16 | {
17 | public partial class DateRangePicker : UserControl
18 | {
19 | public event EventHandler FromDateChanged;
20 | public event EventHandler ToDateChanged;
21 |
22 | public Nullable DateFrom
23 | {
24 | get { return (Nullable)this.GetValue(DateFromProperty); }
25 | set { this.SetValue(DateFromProperty, value); }
26 | }
27 |
28 | public static readonly DependencyProperty DateFromProperty =
29 | DependencyProperty.Register("DateFrom", typeof(Nullable), typeof(DateRangePicker), new PropertyMetadata(DateFrom_PropertyChanged));
30 |
31 |
32 | public Nullable DateTo
33 | {
34 | get { return (Nullable)this.GetValue(DateToProperty); }
35 | set { this.SetValue(DateToProperty, value); }
36 | }
37 |
38 | public static readonly DependencyProperty DateToProperty =
39 | DependencyProperty.Register("DateTo", typeof(Nullable), typeof(DateRangePicker), new PropertyMetadata(DateTo_PropertyChanged));
40 |
41 | public DateRangePicker()
42 | {
43 | this.InitializeComponent();
44 |
45 | this.DatePickerFrom.BlackoutDates.Add(new CalendarDateRange(DateTime.Today.AddDays(1), DateTime.MaxValue));
46 | this.DatePickerTo.BlackoutDates.Add(new CalendarDateRange(DateTime.Today.AddDays(1), DateTime.MaxValue));
47 |
48 | this.DatePickerFrom.SetBinding(DatePicker.SelectedDateProperty, new Binding("DateFrom") { Source = this, Mode = BindingMode.TwoWay });
49 | this.DatePickerTo.SetBinding(DatePicker.SelectedDateProperty, new Binding("DateTo") { Source = this, Mode = BindingMode.TwoWay });
50 | }
51 |
52 | private static void DateFrom_PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
53 | {
54 | DateRangePicker dateRangePicker = (DateRangePicker)obj;
55 | dateRangePicker.DateFromChanged();
56 | }
57 |
58 | private void DateFromChanged()
59 | {
60 | // This updates the blackout dates for DatePickerTo.
61 | this.DatePickerTo.BlackoutDates.Clear();
62 | if (this.DateFrom.HasValue)
63 | {
64 | DateTime dateFrom = this.DateFrom.Value;
65 | if (this.DateTo.HasValue)
66 | {
67 | DateTime dateTo = this.DateTo.Value;
68 | if (dateTo <= dateFrom)
69 | {
70 | this.DateTo = null;
71 | }
72 | }
73 |
74 | this.DatePickerTo.BlackoutDates.Add(new CalendarDateRange(DateTime.MinValue, dateFrom));
75 | }
76 | this.DatePickerTo.BlackoutDates.Add(new CalendarDateRange(DateTime.Today.AddDays(1), DateTime.MaxValue));
77 |
78 | this.OnDateChanged(FromDateChanged);
79 | }
80 |
81 | private static void DateTo_PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
82 | {
83 | DateRangePicker dateRangePicker = (DateRangePicker)obj;
84 | dateRangePicker.OnDateChanged(dateRangePicker.ToDateChanged);
85 | }
86 |
87 | private void OnDateChanged(EventHandler handler)
88 | {
89 | if (handler != null)
90 | {
91 | handler(this, EventArgs.Empty);
92 | }
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/ReusableControls/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("ReusableControls")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("Microsoft")]
14 | [assembly: AssemblyProduct("ReusableControls")]
15 | [assembly: AssemblyCopyright("Copyright © Microsoft 2009")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/ReusableControls/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.21006.1
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ReusableControls.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ReusableControls.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ReusableControls/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/ReusableControls/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.21006.1
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ReusableControls.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ReusableControls/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ReusableControls/ReusableControls.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {37EC527A-D370-4643-A4A5-F585D18244D1}
9 | library
10 | Properties
11 | ReusableControls
12 | ReusableControls
13 | v4.0
14 | Client
15 | 512
16 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
17 | 4
18 |
19 |
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | 4.0
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | MSBuild:Compile
54 | Designer
55 |
56 |
57 | DateRangePicker.xaml
58 | Code
59 |
60 |
61 |
62 |
63 | Code
64 |
65 |
66 | True
67 | True
68 | Resources.resx
69 |
70 |
71 | True
72 | Settings.settings
73 | True
74 |
75 |
76 | ResXFileCodeGenerator
77 | Resources.Designer.cs
78 |
79 |
80 | SettingsSingleFileGenerator
81 | Settings.Designer.cs
82 |
83 |
84 |
85 |
86 |
93 |
--------------------------------------------------------------------------------