<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>samsalisbury.net</title>
	<atom:link href="http://samsalisbury.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://samsalisbury.net</link>
	<description>Ramblings on programming and .NET</description>
	<lastBuildDate>Thu, 11 Mar 2010 10:16:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>RepositoryHosting.com backup script</title>
		<link>http://samsalisbury.net/articles/repositoryhosting-backup-script/</link>
		<comments>http://samsalisbury.net/articles/repositoryhosting-backup-script/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 16:03:30 +0000</pubDate>
		<dc:creator>Sam</dc:creator>
				<category><![CDATA[Scripts]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://samsalisbury.net/?p=84</guid>
		<description><![CDATA[We all know the importance of backups, and backups of backups, but even some of the most respected developers occasionally fail to keep their stuff backed up, as we recently learned&#8230; So here&#8217;s my tiny contribution to the subject, specifically for anyone using the amazingly low-cost RepositoryHosting.com for their SCM (it supports Git, Mercurial and [...]]]></description>
			<content:encoded><![CDATA[<p>We all know the importance of backups, and backups of backups, but even some of the most respected developers occasionally fail to keep their stuff backed up, as we <a href="http://www.codinghorror.com/blog/2009/12/international-backup-awareness-day.html">recently</a> <a href="http://haacked.com/archive/2009/12/14/back-in-business-again.aspx">learned</a>&#8230; So here&#8217;s my tiny contribution to the subject, specifically for anyone using the amazingly low-cost <a href="http://repositoryhosting.com">RepositoryHosting.com</a> for their SCM (it supports Git, Mercurial and SVN) and project management (by way of Trac).</p>
<p>Whilst RepositoryHosting.com already offers <a href="http://repositoryhosting.com/blog/2009/03/06/automated-backups-to-amazon-s3">automatic copying of backups to an Amazon S3 bucket</a>, it&#8217;s always best to not rely on a single backup location, as many stories confirm. In this light, I whizzed up the following script which you can use to pull your backups down to your local workstation or office file server. It&#8217;s a bit rough around the edges, and doesn&#8217;t handle errors, so you will have to check the results after each run, but it sure beats logging in and manually downloading the files through your browser each day&#8230; <strong><em>(Thanks to Matt White at RepositoryHosting.com for changing the backup URLs to make them more predictable, and suggesting the initial idea that spawned this script.)</em></strong></p>
<p>This script relies on a <a href="http://en.wikipedia.org/wiki/Bash">Bash shell</a> with <a href="http://curl.haxx.se/">cURL</a> available, like the one that comes with <a href="http://code.google.com/p/msysgit/">msysgit</a> if you&#8217;re using Windows. You&#8217;ll also need to make sure you set up daily backups in your RepositoryHosting.com project&#8217;s settings.</p>
<p>I&#8217;m no expert on Bash shell scripting, so if you can think of any improvements (to make the script more concise or handle errors etc.) then please feel free to educate us all in the comments!</p>
<p>Here&#8217;s the script&#8230; (I named it &#8220;backup.sh&#8221;). See the comments in-line for configuration instructions.</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh
# RepositoryHosting.com backup download script
#
# This script downloads your daily RepositoryHosting.com backups.

##################################################################
##
### Configuration
##

# Subdomain of your repository
RepoSubdomain=mysubdomain

# Local backup directory
BackupDir=~/Backups/RepositoryHosting.com

# RepositoryHosting.com administrator credentials
Username=myadminusername
Password=mypassword

# List of project names (for naming the backups, the order of these
# equate to the project IDs in your RepositoryHosting.com account.)
ProjectNames=(
	MyProject
	CoolProject
	OtherProject
)

# Backup date formats (e.g. &quot;+%Y%m%d&quot; for YYYYMMDD, or &quot;+%d&quot; for DD)
# NOTE: This affects the number of backups that will be kept, e.g.
# &quot;+%d&quot; will store a month's worth of backups, each numbered as the
# day of the month when it was created, &quot;+%Y%m%d will keep an infinite
# number of backups, as each one will be uniquely dated.
#
# NOTE: This is used only if you specify @Date in the filename format.
#
FileDateFormat=&quot;+%d&quot;

# Subdirectory date format (same as above, used only if you specify
# @Date in your SubDirFormat).
#
#SubDirDateFormat=&quot;+%m&quot;

# Backup subdirectory format. If specified will place your backups into
# a separate subdirectory for each project.
#
SubDirFormat=&quot;@ProjectName&quot;

# Backup file name format (e.g. &quot;@ProjectName.@Date&quot;).
# This will automatically be prepended with the $BackupDir/$SubDir/ and
# appended with &quot;.tar.gz&quot;.
#
FileNameFormat=&quot;@ProjectName.@Date&quot;

##
### End configuration (no need to edit past here)
##
##################################################################

# Resolve URLs
RepoBaseUrl=&quot;https://$RepoSubdomain.repositoryhosting.com&quot;
SessionStartUrl=&quot;$RepoBaseUrl/session&quot;
ProjectsBaseUrl=&quot;$RepoBaseUrl/projects&quot;

# Messages
echo -e &quot;\nDownloading today's backups \n\tFrom:\t$RepoBaseUrl&quot;\
&quot;\n\tTo:\t$BackupDir&quot;

# Cookie file name
CookieFileName=&quot;cookies.txt&quot;

# Create backup directory if it doesn't exist
mkdir -p &quot;$BackupDir&quot;
# Go to backup directory
cd &quot;$BackupDir&quot;

# Login
echo -e &quot;\nLogging in...&quot;
curl -sS -X POST $SessionStartUrl -d \
&quot;username=$Username&amp;password=$Password&quot; -c $CookieFileName -o /dev/null

# Copy project backups
ProjectNumber=0
while [ &quot;x${ProjectNames[ProjectNumber]}&quot; != &quot;x&quot; ]
do
# Specify &amp; create backup subdirectory for this project
ProjectBackupSubdir=\
&quot;${SubDirFormat//@ProjectName/${ProjectNames[ProjectNumber]}}&quot;
ProjectBackupSubdir=\
&quot;${ProjectBackupSubdir//@Date/`date $SubDirDateFormat`}&quot;
test &quot;x$ProjectBackupSubdir&quot; != &quot;x&quot; &amp;&amp; mkdir -p $ProjectBackupSubdir &amp;&amp; \
ProjectBackupSubdir=&quot;$ProjectBackupSubdir/&quot;
# Resolve backup filename
ProjectBackupFile=\
&quot;${FileNameFormat//@ProjectName/${ProjectNames[ProjectNumber]}}&quot;
ProjectBackupFile=\
&quot;${ProjectBackupFile//@Date/`date $FileDateFormat`}.tar.gz&quot;
# Copy project backup
echo -e &quot;\nCopying ${ProjectNames[ProjectNumber]} backup to &quot;\
&quot;\n\t$ProjectBackupSubdir$ProjectBackupFile&quot;
curl -L &quot;$ProjectsBaseUrl/$[ProjectNumber+1]/backups/`date +%Y/%m/%d/00`&quot; \
-b $CookieFileName -# \
-o &quot;$BackupDir/$ProjectBackupSubdir$ProjectBackupFile&quot;
ProjectNumber=$[$ProjectNumber+1]
done

# Delete cookies.txt
rm $CookieFileName

echo -e &quot;\nFinished downloading backups!&quot;
</pre>
<p>If you want to launch this easily in Windows, you can use a simple batch file&#8230;</p>
<pre class="brush: plain; title: ; notranslate">
REM Start the RepositoryHosting.com backup download script
C:
&quot;\Program Files (x86)\Git\bin\sh.exe&quot; -login -c /c/Users/Sam/backup.sh
</pre>
]]></content:encoded>
			<wfw:commentRss>http://samsalisbury.net/articles/repositoryhosting-backup-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic properties in VB.NET</title>
		<link>http://samsalisbury.net/articles/automatic-properties-in-vb-net/</link>
		<comments>http://samsalisbury.net/articles/automatic-properties-in-vb-net/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 14:37:39 +0000</pubDate>
		<dc:creator>Sam</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://samsalisbury.net/?p=66</guid>
		<description><![CDATA[The mind boggles at why Microsoft's decided not to support automatic properties in VB.NET under the .NET Framework 3.5. Here is a description of the problem and a workable (though imperfect) workaround.]]></description>
			<content:encoded><![CDATA[<p>The mind sometimes boggles at Microsoft&#8217;s implementation of VB.NET. One of these logic-defying mysteries is why VB.NET, in the .NET Framework 3.5, does not support automatic properties using similar syntax to C#. Automatic properties are a way to generate a private field, along with a two accessor methods (get and set) with independant levels of data hiding. They look like this in C#&#8230;</p>
<pre class="brush: csharp; title: ; notranslate">
// A publically readable but only privately writeable string
public string aStringProperty { get; private set; }
</pre>
<p>The code above is expanded by the compiler to create a private string field, a private set method and a public get method, something that would look something akin to this (with the addition of having the &#8216;=&#8217; operator overloaded to provide automatic calls to these accessor methods when necessary)&#8230;</p>
<pre class="brush: csharp; title: ; notranslate">
// A publically readable but only privately writeable string
private string _StringProperty;
public string get_StringProperty { return _aStringProperty; }
private string set_StringProperty { _aStringProperty = value; }
</pre>
<p>However in VB.NET the situation is much worse! Look at this mess&#8230;</p>
<pre class="brush: vb; title: ; notranslate">
Private _StringProperty As String
Public Property StringProperty As String
	Get
		Return _StringProperty
	End Get
	Private Set(ByVal value As String)
		_StringProperty = value
	End Set
End Property
</pre>
<p>That&#8217;s right, 9 lines of code in VB.NET, that can be written using only 1 in C#. And VB is meant to be easier?!</p>
<h2>What&#8217;s so great about <em>properties</em> anyway?</h2>
<p>One of the main reasons I use properties as opposed to just public data members in my ASP.NET applications is that once you have defined a <a href="http://www.google.co.uk/search?q=web+user+control" title="Google search for 'web user control'">web user control</a> with public properties, these properties added to the Intellisense database, helping you out when inserting the web user control into another control or page. This is mighty useful when writing a control that will be consumed by people who don&#8217;t know, or shouldn&#8217;t need to know the internal workings of the control. However, simple public fields, i.e. those declared in VB.NET thusly&#8230;
<pre class="brush: vb; title: ; notranslate">Public SomePublicField As String</pre>
<p> &#8230;do not get this Intellisense treatment. They can be manually typed into the aspx code as attributes to the web user control, however without Intellisense to guide the way, many developers will thus assume that the attribute with this name is not available to them.</p>
<p>Maybe Microsoft should look into adding Intellisense support for such simple public data members? But I guess that&#8217;s something for the commenters to discuss! Even better would be proper automatic properties for VB.NET, as there seems to be something good about only exposing properly encapsulated properties to the aspx code.</p>
]]></content:encoded>
			<wfw:commentRss>http://samsalisbury.net/articles/automatic-properties-in-vb-net/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Paginated ListView with ObjectDataSource minimal example</title>
		<link>http://samsalisbury.net/articles/objectdatasource-listview-paging-minimal-example/</link>
		<comments>http://samsalisbury.net/articles/objectdatasource-listview-paging-minimal-example/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 17:38:26 +0000</pubDate>
		<dc:creator>Sam</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Minimal Examples]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[ListView]]></category>
		<category><![CDATA[ObjectDataSource]]></category>
		<category><![CDATA[Pagination]]></category>
		<category><![CDATA[Paging]]></category>
		<category><![CDATA[VB.NET]]></category>

		<guid isPermaLink="false">http://samsalisbury.net/?p=3</guid>
		<description><![CDATA[In this minimal example, we create an ASP.NET web form that contains a paginated <code>ListView</code> control, bound to an <code>ObjectDataSource</code> control.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been wrestling with the <code>ObjectDataSource</code> control recently, and couldn&#8217;t find a minimal example of how it all hooks up, for simple, paged, read-only usage, <em>anywhere</em>. Therefore, I now present the paginated <code>ListView</code> with <code>ObjectDataSource</code> minimal example. Try to stay awake&#8230;</p>
<h2 id="section-introduction">Introduction</h2>
<p>In this minimal example, we will create an ASP.NET web form that contains a paginated (or &#8220;paged&#8221; in .Net parlance) <code>ListView</code> control, bound to an <code>ObjectDataSource</code>. In order to avoid any complex database access code mucking up the important part of this example, I&#8217;ll instead use the built-in collection of <code>CultureInfo</code> objects that come with the .Net Framework. So, the &#8216;business object&#8217; collection we are displaying in the <code>ListView</code> will be a <code>List&lt;CultureInfo&gt;</code> (that&#8217;s a <code>List(Of CultureInfo)</code> for any VB.NET folk out there. Hopefully this will make for a semi-interesting tutorial&#8230;</p>
<h2 id="section-part1">Part 1: The markup</h2>
<p>Of course, the first thing we will need is an aspx page containing the necessary controls for our minimal example &#8212; the important ones to include are <code>ObjectDataSource</code>, <code>ListView</code> and <code>DataPager</code>. Their opening tags are highlighted in the code below, note that the <code>DataPager</code> is inside the <code>LayoutTemplate</code> of the <code>ListView</code>. This doesn&#8217;t have to be the case, in which case you&#8217;d have to also provide the attribute <code>PagedControlID</code> to tell it which <code>IPageableItemContainer</code> compatible control to paginate.</p>
<pre class="brush: xml; highlight: [1,6,8]; title: ; notranslate">
&lt;asp:ObjectDataSource ID=&quot;ObjectDataSource1&quot; runat=&quot;server&quot;
	EnablePaging=&quot;true&quot; OnSelecting=&quot;ObjectDataSource1_Selecting&quot;
	TypeName=&quot;WebApplication1.MinimalObjectDataSourceObject&quot;
	SelectMethod=&quot;MinimalSelectMethod&quot; SelectCountMethod=&quot;MinimalSelectCountMethod&quot; /&gt;

&lt;asp:ListView ID=&quot;ListView1&quot; runat=&quot;server&quot; DataSourceID=&quot;ObjectDataSource1&quot;&gt;
	&lt;LayoutTemplate&gt;Select page...
		&lt;asp:DataPager ID=&quot;DataPager1&quot; runat=&quot;server&quot;&gt;
			&lt;Fields&gt;&lt;asp:NumericPagerField /&gt;&lt;/Fields&gt;
		&lt;/asp:DataPager&gt;
		&lt;ul&gt;&lt;li id=&quot;itemPlaceholder&quot; runat=&quot;server&quot; /&gt;&lt;/ul&gt;
	&lt;/LayoutTemplate&gt;
	&lt;ItemTemplate&gt;
		&lt;li runat=&quot;server&quot;&gt;
			&lt;%#Eval(&quot;EnglishName&quot;) %&gt; &amp;mdash; &lt;em&gt;&lt;%#Eval(&quot;NativeName&quot;) %&gt;&lt;/em&gt;
		&lt;/li&gt;
	&lt;/ItemTemplate&gt;
&lt;/asp:ListView&gt;
</pre>
<p>We&#8217;ll refer back to this code later, important points to note for now are that</p>
<ul>
<li>the <code>ObjectDataSource</code> has <code>EnablePaging</code> set to <code>true</code> and has its <code>OnSelecting</code>, <code>TypeName</code>, <code>SelectMethod</code> and <code>SelectCountMethod</code> attributes set, and</li>
<li>the <code>ListView</code> has its <code>DataSourceID</code> set to the ID of the <code>ObjectDataSource</code>.</li>
</ul>
<h2 id="section-part2">Part 2: The enfunctioning</h2>
<p>The <code>ObjectDataSource</code> control requires that you implement at least 2 functions (if you only want to READ data, as we are doing here). The first function, referred to as the <em>SelectMethod</em>, must return the <code>IEnumerable</code> of items for the page of data you want to display. The second, referred to as the <em>SelectCountMethod</em> should return the count of all the items in the data set. Not just the number on the first page! No no no! The number of items in total across all the pages! Yes yes yes! This often forces us to do some caching if we are to be efficient, however, we are dealing with an absolutely minimal example here, so I&#8217;ll leave that for a future article.</p>
<p>These methods must be <code>public</code> and can exist practically anywhere accessible to your <code>ObjectDataSource</code>. For the purposes of this article, they should also be <code>static</code> (that&#8217;s <code>Shared</code> for any VB.NET folk). In fact, this is not strictly necessary, but we are dealing with a simple, <em>minimal</em> example here, so we don&#8217;t need to worry about this for the moment.</p>
<dl>
<dt>SelectMethod <em>(MinimalSelectMethod)</em></dt>
<dd>The <em>SelectMethod</em> must accept as arguments any parameters that you want to use to select your data (e.g. any search terms or filters you want applied), plus 2 more parameters: <em>startRowIndex</em> and <em>maximumRows</em>. These final two are used for paging. They must have the exact names I&#8217;ve used here, unless you want to specify custom names in the properties of the <code>ObjectDataSource</code>. Personally I&#8217;d just use the default names, if you&#8217;ve come this far it&#8217;s unlikely your class will be used to do anything else other than provide data to an <code>ObjectDataSource</code>.</dd>
<dt>SelectCountMethod <em>(MinimalSelectCountMethod)</em></dt>
<dd>The <em>SelectCountMethod</em> needs to provide the total number of rows that should be returned by your query. Therefore, it also needs to be passed any parameters needed to filter the data. It doesn&#8217;t care about which page you want to view, so your custom parameters are all that&#8217;s needed.</dd>
</dl>
<p>So, here is a complete class exposing both of these methods (it also uses a helper method I&#8217;ve called &#8220;GetSomeKindOfList&#8221; to do the list filtering, it&#8217;s pretty simple so I won&#8217;t explain it here).</p>
<pre class="brush: csharp; highlight: [8,9,19]; title: ; notranslate">
public class MinimalObjectDataSourceObject
{
	// A nice list for demonstration purposes.
	private static List&lt;CultureInfo&gt; baseList =
		new List&lt;CultureInfo&gt;(CultureInfo.GetCultures(CultureTypes.AllCultures));

	// Our minimal SelectMethod.
	public static List&lt;CultureInfo&gt; MinimalSelectMethod(
		string parameter1, string parameter2, int startRowIndex, int maximumRows)
	{
		List&lt;CultureInfo&gt; someList = GetSomeKindOfList(parameter1, parameter2);
		// Make sure we don't try to get objects that don't exist, ArgumentOutOfRangeException otherwise!
		if (startRowIndex + maximumRows &gt; someList.Count)
		{ maximumRows = someList.Count - startRowIndex; }
		return someList.GetRange(startRowIndex, maximumRows);
	}

	// Our minimal SelectCountMethod.
	public static int MinimalSelectCountMethod(string parameter1, string parameter2)
	{
		return GetSomeKindOfList(parameter1, parameter2).Count;
	}

	// A method to get a filtered list for our primary data source.
	public static List&lt;CultureInfo&gt; GetSomeKindOfList(string parameter1, string parameter2)
	{
		return baseList.FindAll(x =&gt; x.EnglishName.ToLower().StartsWith(parameter1))
			.FindAll(x =&gt; string.IsNullOrEmpty(parameter2.ToLower()) ||
				x.EnglishName.ToLower().EndsWith(parameter2.ToLower()));
	}
}
</pre>
<p>So, as you might have guessed, lines 8 and 19 are the important ones here, containing our 2 methods. These methods can be called anything you like here, as long as the <a href="#section-part1">attributes in your <code>ObjectDataSource</code> tag</a> are spelt exactly the same.</p>
<p>We&#8217;re almost there! Don&#8217;t have a baby yet though, the nasty bit&#8217;s coming&#8230;</p>
<h2 id="section-part3">Part 3: Pass the [parameter(s)]</h2>
<p>Now we have the basic functions in place, we need to find some way to pass the parameters to the <code>ObjectDataSource</code>, so the results can be selected in any way that pleases us. This is the part that I found particularly difficult when implementing this for the first time, so pay attention!</p>
<p>The <code>ObjectDataSource</code> will automatically call its <code>Selecting</code> event, each time it needs to load a page of data for the <code>ListView</code>. It is here, and nowhere else, that we must programmatically set the parameters for our <em>SelectMethod</em> and our <em>SelectCountMethod</em>. This event receives an <code>ObjectDataSourceSelectingEventArgs</code> object as its second parameter, which in turn contains an <code>IOrderedDictionary</code> collection called <em>InputParameters</em>. So, you guessed it, we just need to set this up with the values we want to pass to our <em>SelectMethod</em> (and our <em>SelectCountMethod</em>). The names of the parameters must be <em>exactly</em> the same as the names we used in our definition of the <em>SelectMethod</em> and <em>SelectCountMethod</em> (the functions I&#8217;ve named <em>MinimalSelectMethod</em> and <em>MinimalSelectCountMethod</em>. We do this thusly&#8230;</p>
<pre class="brush: csharp; title: ; notranslate">
protected void ObjectDataSource1_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
	e.InputParameters[&quot;parameter1&quot;] = TextBox1.Text;
	e.InputParameters[&quot;parameter2&quot;] = TextBox2.Text;
}
</pre>
<p>Remember the <em>OnSelecting</em> property of our <code>ObjectDataSource</code> tag in the aspx code from before? Well, this is the function whose name it must be set to. <em>(Note, if you&#8217;re using VB.NET, then you don&#8217;t need to bother with defining the <em>OnSelecting</em> property in the aspx code, you just need a <code>Sub</code> that says <code>Handles ObjectDataSource1.Selecting</code> at the end of the first line of its definition. You also need to give it the same parameters as specified here.)</em></p>
<p>And that&#8217;s it, it should now work. Give yourself a big pat on the back.</p>
<p>Just one final note though. Since the <code>Selecting</code> event of the <code>ObjectDataSource</code> will be called each time a page is requested, the code I&#8217;ve used here could potentially cause an exception. <em>&#8220;Really? Wow, how&#8217;s that?&#8221;</em> I hear a little voice in my ear ask. Well, let&#8217;s go on a journey&#8230;</p>
<h2 id="section-notes">Daemons and devels</h2>
<p>Actually, let&#8217;s not. Here&#8217;s why: the number of pages available when the <code>DataPager</code> was rendered may be different than the number of pages available after one of the page buttons is selected, in our example. This could happen for one of two reasons.</p>
<ul>
<li>Firstly, the parameters may end up reducing the number of pages available, if they have been changed since the <code>DataPager</code> was rendered.</li>
<li>Secondly, the actual source dataset itself may have changed since the <code>DataPager</code> was rendered, meaning that any pages that are selected beyond the new number will not exist, and will therefore cause exceptions to be thrown.</li>
</ul>
<p>I want to keep this article short, so I&#8217;ll simply outline a strategy to mitigate these potential exceptions. I&#8217;ve included a project in the accompanying download that has this implemented.</p>
<h3>Avoiding exceptions</h3>
<p>In my opinion, going to a different page in our dataset oughtn&#8217;t to be able to change the filter parameters, it just seems like unexpected behaviour to me. Therefore, as you&#8217;ll see in the attached project, one solution is to store the parameters&#8217; current values separately from the controls&#8217; current values, in the <code>Session</code> collection, only updating them when the &#8216;Search&#8217; button is clicked.</p>
<h2 id="section-summary">This is the end</h2>
<p>I&#8217;m going to try and draw a nice little diagram to illustrate the relationships between the pieces of code discussed, and post it here to serve as a quick reference. I&#8217;ll also upload the sample project very soon. Watch this space.</p>
<p>So, there you go. If you have anything to add, whinge about, or just want to give me a little ego boost (who wouldn&#8217;t?), then comments go in the box underneath. Ta.</p>
]]></content:encoded>
			<wfw:commentRss>http://samsalisbury.net/articles/objectdatasource-listview-paging-minimal-example/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

