661 lines
26 KiB
HTML
661 lines
26 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||
<head>
|
||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||
<title>Loading Thumbnails</title>
|
||
<link href="style.css" rel="stylesheet" type="text/css">
|
||
<link href="prettify.css" type="text/css" rel="stylesheet">
|
||
<script type="text/javascript" src="prettify.js"></script><script type="text/javascript" src="lang-vb.js"></script><link href="../resources/main.css" media="screen" rel="stylesheet" type="text/css">
|
||
</head>
|
||
<body onload="prettyPrint()"><div class="placing">
|
||
<br><table class="navigation"><tr>
|
||
<td class="navigation-previous"><a href="chapter-layout.html"><strong>
|
||
« Layout</strong></a></td>
|
||
<td class="navigation-index"><a href="../../../better-thumbnail-browser/documentation.html"><strong>Index</strong></a></td>
|
||
<td class="navigation-next"><a href="chapter-text-formatting.html"><strong>Text Formatting »
|
||
</strong></a></td>
|
||
</tr></table>
|
||
<br><h1>Loading Thumbnails</h1>
|
||
<div class="banner">
|
||
<a href="../../../better-thumbnail-browser.html"><img src="../resources/better-thumbnail-browser-overview.gif" alt="Better Thumbnail Browser" class="ss"></a>
|
||
<div class="inside">
|
||
<div class="text">Better Thumbnail Browser for .NET (C#, VB) - Image thumbnail viewing and loading control</div>
|
||
<span class="dbtn-c dbtn-hilight"><span class="dbtn-w"><a href="../../../betterthumbnailbrowser.exe" class="dbtn">Download</a></span></span>
|
||
<span class="dbtn-c"><span class="dbtn-w"><a href="../../../better-thumbnail-browser.html" class="dbtn">More Info</a></span></span>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
|
||
<h2>Loading Images from a Folder</h2>
|
||
|
||
|
||
<p>You can populate Better Thumbnail Browser with auto-population in
|
||
case you want to display images from an image folder:</p>
|
||
|
||
<p><strong>C#</strong></p>
|
||
<pre class="prettyprint"><code class="lang-cs">thumbnailBrowser.Path = "c:\\images";</code></pre>
|
||
|
||
<p><strong>Visual Basic</strong></p>
|
||
<pre class="prettyprint"><code class="lang-vb">thumbnailBrowser.Path = "c:\images"</code></pre>
|
||
|
||
<p>This will automatically add items to Better Thumbnail Browser and
|
||
starts loading them using default image loading provider:</p>
|
||
|
||
<p class="images"><img src="using-auto-populate.png"></p>
|
||
|
||
|
||
<h2>Starting, Stopping and Restarting Loading</h2>
|
||
|
||
|
||
<p>You can control item loading by calling <span class="code">StartLoading()</span>,
|
||
<span class="code">StopLoading()</span> and <span class="code">RestartLoading()</span>
|
||
methods.</p>
|
||
|
||
<p>The <span class="code">StartLoading()</span> method is asynchronous, so the code
|
||
will continue after the call and the thumbnail items will be loaded on a
|
||
separate thread.</p>
|
||
|
||
<p>The <span class="code">StopLoading()</span> method is synchronous - it will wait
|
||
until current item finishes loading and then stops.</p>
|
||
|
||
<p>The <span class="code">RestartLoading()</span> method has an override with
|
||
<span class="code">LoadingRestartOptions</span> parameter. It can have the following
|
||
values:</p>
|
||
|
||
<ul style="list-style:none">
|
||
<li>
|
||
<span class="code">None</span><ul style="list-style:none"><li>
|
||
<p>Restart loading if already running. Do not start loading if
|
||
not running.</p>
|
||
</li></ul>
|
||
</li>
|
||
<li>
|
||
<span class="code">StopLoading</span><ul style="list-style:none"><li>
|
||
<p>Stop loading and then start from beginning.</p>
|
||
</li></ul>
|
||
</li>
|
||
<li>
|
||
<span class="code">CanStartLoading</span><ul style="list-style:none"><li>
|
||
<p>Restart loading if already running. Start loading even if not
|
||
running.</p>
|
||
</li></ul>
|
||
</li>
|
||
</ul>
|
||
<p>When calling <span class="code">RestartLoading()</span> method without
|
||
parameters, the <span class="code">LoadingRestartOptions.None</span> is used.</p>
|
||
|
||
|
||
<h2>Loading Events</h2>
|
||
|
||
|
||
<p>During the loading process, two events are raised by the Better
|
||
ThumbnailBrowser control:</p>
|
||
|
||
<ul style="list-style:none">
|
||
<li>
|
||
<span class="code">ItemLoaded</span><ul style="list-style:none"><li>
|
||
<p>This event is raised whenever a single item is loaded by a
|
||
loading provider. The event can be raised multiple times for a
|
||
single item if a multi-pass loading (see section <strong><em><a href="chapter-loading.html#multi-pass-loading">Multi-pass Loading</a></em></strong>) is used.
|
||
Event data contains loaded item instance, pass index, total number
|
||
of passes and order in which the item is loaded (the order can be
|
||
different from the item index, see section <strong><em><a href="chapter-loading.html#custom-loading-order">Custom Loading
|
||
Order</a></em></strong>).</p>
|
||
</li></ul>
|
||
</li>
|
||
<li>
|
||
<span class="code">LoadingFinised</span><ul style="list-style:none"><li>
|
||
<p>This event is raised when thumbnail item loading finishes for
|
||
whatever reason (no more items to load, loading cancelled by the
|
||
user, loading failed). Event data contains index of item on which
|
||
the loading finished/stopped (<span class="code">LoadingFinishReason</span>
|
||
enumeration), reason why the loading ended and
|
||
<span class="code">System.Exception</span> instance in case the loading failed
|
||
because exception occured on the loading thread.</p>
|
||
</li></ul>
|
||
</li>
|
||
</ul>
|
||
<h2>Loading Options</h2>
|
||
|
||
|
||
<h2>Refreshing Delay</h2>
|
||
|
||
|
||
<p>When large number of small thumbnails are loaded, or when loading
|
||
each thumbnail is quick, it is inefficient to refresh control after
|
||
every single item is loaded. Instead, a timer looks for loaded items in
|
||
a predefined interval and refreshes the control only if any items get
|
||
loaded. By default, the interval is set to 250 millisecons, but you can
|
||
set your own value through <span class="code">RefreshDelay</span> property. When you
|
||
set property value to <span class="code">0</span>, the control will be refreshed
|
||
after every item loaded.</p>
|
||
|
||
<p>Better Thumbnail Browser uses <span class="code">System.Threading.Timer</span>,
|
||
so its accurracy is in order of tens of milliseconds.</p>
|
||
|
||
|
||
<h2>Loading Thread Options</h2>
|
||
|
||
|
||
<p>You can setup thumbnail item loading thread by setting the
|
||
following properties:</p>
|
||
|
||
<ul style="list-style:none">
|
||
<li>
|
||
<span class="code">LoadingThreadIsBackground</span><ul style="list-style:none"><li>
|
||
<p>Specifies whether the item loading thread runs as a
|
||
background thread.</p>
|
||
</li></ul>
|
||
</li>
|
||
<li>
|
||
<span class="code">LoadingThreadPriority</span><ul style="list-style:none"><li>
|
||
<p>Specified item loading thread priority
|
||
(<span class="code">System.Threading.ThreadPriority</span>).</p>
|
||
</li></ul>
|
||
</li>
|
||
</ul>
|
||
<h2>Skipping Individual Items</h2>
|
||
|
||
|
||
<p>If you want <strong><em>not to</em></strong> load specific thumbnail
|
||
items, set <span class="code">BetterThumbnailBrowserItem.Skip</span> property to
|
||
<span class="code">true</span>.</p>
|
||
|
||
|
||
|
||
<h2>Loading Providers</h2>
|
||
|
||
|
||
<p>Thumbnail item loading is performed by so called <strong><em>loading
|
||
providers</em></strong> (instances of <span class="code">LoadingProvider</span>
|
||
class).</p>
|
||
|
||
<p>These instances are listed in the <span class="code">LoadingProviders</span>
|
||
property. In case there is more than one loading provider, a multiple
|
||
passes over the thumbnail items are done, one for each loading
|
||
provider.</p>
|
||
|
||
<p>Better Thumbnail Browser have two bases classes for deriving your own
|
||
loading providers:</p>
|
||
|
||
<ul style="list-style:none">
|
||
<li>
|
||
<span class="code">CustomLoadingProvider</span><ul style="list-style:none"><li>
|
||
<p>Intended for loading non-image data.</p>
|
||
</li></ul>
|
||
</li>
|
||
<li>
|
||
<span class="code">ImageLoadingProvider</span><ul style="list-style:none"><li>
|
||
<p>Intended for loading image thumbnails.</p>
|
||
</li></ul>
|
||
</li>
|
||
</ul>
|
||
<p>The both of these classes are derived from
|
||
<span class="code">LoadingProvider</span> class and implement a <span class="code">LoadItem</span>
|
||
method. In this method, the loader calls <span class="code">LoadItemAsync</span>
|
||
method, which have to be provided by the user as well as the
|
||
<span class="code">LoadItemSync</span> method. The difference between these two methods
|
||
is that <span class="code">LoadItemAsync</span> is called on the (background) loader
|
||
thread and the <span class="code">LoadItemSync</span> is then called on the UI
|
||
(foreground) thread.</p>
|
||
|
||
<p>Only <span class="code">LoadItemAsync</span> and <span class="code">LoadItemSync</span>
|
||
methods need to be implemented by the user.</p>
|
||
|
||
<p>There is also <span class="code">LoadItemsSync</span> method which is used by
|
||
<span class="code">LoadItem</span> when timer is used (see <span class="code">RefreshDelay</span>
|
||
property), in that case, the loading provider calls only
|
||
<span class="code">LoadItemAsync</span> and stores the result data, and then performs
|
||
synchronization and calls <span class="code">LoadItemSync</span> in a batch.</p>
|
||
|
||
<h2>Loading Image Thumbnails in Better Thumbnail Browser</h2>
|
||
|
||
|
||
<p>Thumbnail loading is designed to be fast and effective.</p>
|
||
|
||
<p>First of all, images need not to be loaded in full resolution and
|
||
resized. Instead, you can load image in lower resolution or simply get
|
||
low resolution version already available. For example, the default image
|
||
loading provider in Better Thumbnail Browser makes use of existing image
|
||
thumbnails in JPEG image, avoiding resizing.</p>
|
||
|
||
<p>You can still load images in full resolution. These images will be
|
||
present in <span class="code">BetterThumbnailBrowser.Image</span> property in full
|
||
resolution, but will be resized internally for viewing.</p>
|
||
|
||
<p>The thumbnail items can be zoomed and images may need to be
|
||
reloaded in higher resolution. The loading mechanism of Better
|
||
ThumbnailBrowser never reloads images if a full resolution is already
|
||
loaded (smaller image gets centered in the thumbnail item instead). It
|
||
also avoid reloading if user provided image of high-enough resolution.
|
||
Of course, if you provide image in full resolution, then every thumbnail
|
||
item gets loaded just once. To determine what "full resolution" means,
|
||
there is a <span class="code">maximumImageSize</span> property in the loading method.
|
||
One provides loaded image and informs about the full resolution. You can
|
||
also set <span class="code">maximumImageSize</span> property to the same size as
|
||
thumbnail image, but your image will not be reloaded in higher
|
||
resolution if needed (and get centered in thumbnail items
|
||
instead).</p>
|
||
|
||
|
||
<h2>Custom Image Loader</h2>
|
||
|
||
|
||
<p>We will illustrate how to implement a minimalist image loading
|
||
provider. It assumes that every item contains path to image file in its
|
||
<span class="code">Path</span> property:</p>
|
||
|
||
<p><strong>C#</strong></p>
|
||
<pre class="prettyprint"><code class="lang-cs">class MyImageLoadingProvider : ImageLoadingProvider
|
||
{
|
||
public MyLoadingProvider(BetterThumbnailBrowser thumbnailBrowser)
|
||
: base(thumbnailBrowser)
|
||
{
|
||
}
|
||
|
||
protected override void LoadItemAsync(
|
||
BetterThumbnailBrowserItem item,
|
||
Size targetImageSize,
|
||
out Image image,
|
||
out Size maximumImageSize,
|
||
out ILoadingProviderData data)
|
||
{
|
||
image = Image.FromFile(item.Path);
|
||
maximumImageSize = image.Size;
|
||
data = null;
|
||
}
|
||
}</code></pre>
|
||
|
||
<p><strong>Visual Basic</strong></p>
|
||
<pre class="prettyprint"><code class="lang-vb">Class MyImageLoadingProvider
|
||
Inherits ImageLoadingProvider
|
||
|
||
Public Sub New(thumbnailBrowser As BetterThumbnailBrowser)
|
||
MyBase.New(thumbnailBrowser)
|
||
End Sub
|
||
|
||
Protected Overrides Sub LoadItemAsync(
|
||
item As BetterThumbnailBrowserItem,
|
||
targetImageSize As Size,
|
||
ByRef image As Image,
|
||
ByRef maximumImageSize As Size,
|
||
ByRef data As ILoadingProviderData)
|
||
|
||
image = Image.FromFile(item.Path)
|
||
maximumImageSize = image.Size
|
||
data = Nothing
|
||
|
||
End Sub
|
||
|
||
End Class</code></pre>
|
||
|
||
<p>As you can see, the implementation is very simple.</p>
|
||
|
||
<p>The entire code of <span class="code">LoadItemAsync</span> consists of just
|
||
providing these three parameters:</p>
|
||
|
||
<ul style="list-style:none">
|
||
<li>
|
||
<span class="code">image</span><ul style="list-style:none"><li>
|
||
<p>Loaded thumbnail image.</p>
|
||
</li></ul>
|
||
</li>
|
||
<li>
|
||
<span class="code">maximumImageSize </span><ul style="list-style:none"><li>
|
||
<p>Maximum allowed thumbnail size. This is actually size of a
|
||
full resolution image, even if you have loaded smaller image (a
|
||
thumbnail). This value informs loaded that there is a higher
|
||
resolution available and it can re-load image in higher resolution
|
||
if needed.</p>
|
||
</li></ul>
|
||
</li>
|
||
<li>
|
||
<span class="code">data</span><ul style="list-style:none"><li>
|
||
<p>Custom non-image data we would like to pass to UI thread. We
|
||
can use any user types, they only need to implement trivial
|
||
<span class="code">ILoadingProviderData</span> interface.</p>
|
||
</li></ul>
|
||
</li>
|
||
</ul>
|
||
<p>The <span class="code">LoadItemSync</span> method need not to be provided by
|
||
the user since it is already implemented in the
|
||
<span class="code">ImageLoadingProvider</span>. The default implementation only takes
|
||
the <span class="code">image</span> and <span class="code">maximumImageSize</span> and sets it
|
||
into respective properties of item:
|
||
<span class="code">BetterThumbnailBrowserItem.Image</span> and
|
||
<span class="code">BetterThumbnailBrowserItem.MaximumImageSize</span>.</p>
|
||
|
||
|
||
<h2>Loading Non-image Data</h2>
|
||
|
||
|
||
<p>Sometimes one would like to load other than image data - for
|
||
example: metadata embedded in photos, file information, retrieve item
|
||
info from remote database etc.</p>
|
||
|
||
<p>This is where <span class="code">CustomLoadingProvider</span> comes into place.
|
||
It is more general, so it can be used for loading images as well. User
|
||
have to provide both <span class="code">LoadImageAsync</span> and
|
||
<span class="code">LoadItemSync</span> methods:</p>
|
||
|
||
<p><strong>C#</strong></p>
|
||
<pre class="prettyprint"><code class="lang-cs">class MyCustomLoadingProvider : CustomLoadingProvider
|
||
{
|
||
public MyCustomLoadingProvider(BetterThumbnailBrowser thumbnailBrowser)
|
||
: base(thumbnailBrowser)
|
||
{
|
||
}
|
||
|
||
protected override void LoadItemAsync(
|
||
BetterThumbnailBrowserItem item,
|
||
Size targetImageSize,
|
||
out ILoadingProviderData data)
|
||
{
|
||
// obtain custom data (this runs on background thread)
|
||
MyLoadingProviderData myLoadingProviderData = /* obtain the data here */;
|
||
|
||
data = myLoadingProviderData;
|
||
}
|
||
|
||
protected override void LoadItemSync(BetterThumbnailBrowserItem item, ILoadingProviderData data)
|
||
{
|
||
MyLoadingProviderData myLoadingProviderData = (MyLoadingProviderData)data;
|
||
|
||
// set loaded data to item (this runs on main thread)
|
||
item.Text = myLoadingProviderData.Label;
|
||
item.ToolTips.Add(new BetterListViewToolTipInfo(BetterListViewToolTipLocation.Image, myLoadingProviderData.Description));
|
||
}
|
||
}</code></pre>
|
||
|
||
<p><strong>Visual Basic</strong></p>
|
||
<pre class="prettyprint"><code class="lang-vb">Class MyCustomLoadingProvider
|
||
Inherits CustomLoadingProvider
|
||
|
||
Public Sub New(thumbnailBrowser As BetterThumbnailBrowser)
|
||
MyBase.New(thumbnailBrowser)
|
||
End Sub
|
||
|
||
Protected Overrides Sub LoadItemAsync(item As BetterThumbnailBrowserItem, targetImageSize As Size, ByRef data As ILoadingProviderData)
|
||
|
||
' obtain custom data (this runs on background thread)
|
||
Dim myLoadingProviderData As MyLoadingProviderData = ' obtain the data here
|
||
|
||
data = myLoadingProviderData
|
||
|
||
End Sub
|
||
|
||
Protected Overrides Sub LoadItemSync(item As BetterThumbnailBrowserItem, data As ILoadingProviderData)
|
||
|
||
Dim myLoadingProviderData As MyLoadingProviderData = DirectCast(data, MyLoadingProviderData)
|
||
|
||
' set loaded data to item (this runs on main thread)
|
||
item.Text = myLoadingProviderData.Label
|
||
item.ToolTips.Add(New BetterListViewToolTipInfo(BetterListViewToolTipLocation.Image, myLoadingProviderData.Description))
|
||
|
||
End Sub
|
||
|
||
End Class</code></pre>
|
||
|
||
<p>As you can see, we have used custom type
|
||
<span class="code">MyLoadingProviderData</span> to hold loaded data, which is passed
|
||
to foreground thread to further processing. This type implements
|
||
<span class="code">ILoadingProviderData</span> - an empty interface - so its code is
|
||
very simple:</p>
|
||
|
||
<p><strong>C#</strong></p>
|
||
<pre class="prettyprint"><code class="lang-cs">class MyLoadingProviderData : ILoadingProviderData
|
||
{
|
||
public string Label
|
||
{
|
||
get;
|
||
set;
|
||
}
|
||
|
||
public string Description
|
||
{
|
||
get;
|
||
set;
|
||
}
|
||
}</code></pre>
|
||
|
||
<p><strong>Visual Basic</strong></p>
|
||
<pre class="prettyprint"><code class="lang-vb">Class MyLoadingProviderData
|
||
Implements ILoadingProviderData
|
||
|
||
Public Property Label() As String
|
||
Get
|
||
Return label
|
||
End Get
|
||
Set
|
||
label = Value
|
||
End Set
|
||
End Property
|
||
|
||
Public Property Description() As String
|
||
Get
|
||
Return description
|
||
End Get
|
||
Set
|
||
description = Value
|
||
End Set
|
||
End Property
|
||
|
||
Private label As String
|
||
Private description As String
|
||
|
||
End Class</code></pre>
|
||
|
||
|
||
<h2>
|
||
<a name="custom-loading-order" id="custom-loading-order"></a>Custom Loading
|
||
Order</h2>
|
||
|
||
|
||
<p>You can specify custom order in which the items will be loaded by
|
||
setting an <span class="code">IComparer<BetterThumbnailBrowserItem></span>
|
||
instance in the <span class="code">LoadingProvider.ItemComparer</span> property. This
|
||
can result in loading images in order you want:</p>
|
||
|
||
<p></p>
|
||
<p class="images"><img src="loading-custom-order.png"></p>
|
||
|
||
<p>For example, we would like to load visible items first, then all
|
||
the others. This can be done with the following comparer:</p>
|
||
|
||
<p><strong>C#</strong></p>
|
||
<pre class="prettyprint"><code class="lang-cs">class CustomOrderItemComparer : IComparer<BetterThumbnailBrowserItem>
|
||
{
|
||
private readonly BetterThumbnailBrowser thumbnailBrowser;
|
||
|
||
public CustomOrderItemComparer(BetterThumbnailBrowser thumbnailBrowser)
|
||
{
|
||
this.thumbnailBrowser = thumbnailBrowser;
|
||
}
|
||
|
||
int IComparer<BetterThumbnailBrowserItem>.Compare(BetterThumbnailBrowserItem itemA, BetterThumbnailBrowserItem itemB)
|
||
{
|
||
// get put visible item indices in sorted array
|
||
ReadOnlyCollection<BetterListViewItem> visibleItems = this.thumbnailBrowser.VisibleItems;
|
||
int[] visibleIndices = new int[visibleItems.Count];
|
||
|
||
for (int indexItem = 0; indexItem < visibleItems.Count; indexItem++)
|
||
{
|
||
visibleIndices[indexItem] = visibleItems[indexItem].Index;
|
||
}
|
||
|
||
Array.Sort(visibleIndices);
|
||
|
||
int valueA = ((Array.BinarySearch(visibleIndices, itemA.Index) >= 0) ? 0 : 1);
|
||
int valueB = ((Array.BinarySearch(visibleIndices, itemB.Index) >= 0) ? 0 : 1);
|
||
|
||
// compare items according to their visibility
|
||
int result = valueA.CompareTo(valueB);
|
||
|
||
if (result != 0)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
// compare items according to their indices
|
||
valueA = itemA.Index;
|
||
valueB = itemB.Index;
|
||
|
||
return valueA.CompareTo(valueB);
|
||
}
|
||
}</code></pre>
|
||
|
||
<p><strong>Visual Basic</strong></p>
|
||
<pre class="prettyprint"><code class="lang-vb">Class CustomOrderItemComparer
|
||
Implements IComparer(Of BetterThumbnailBrowserItem)
|
||
|
||
Private ReadOnly thumbnailBrowser As BetterThumbnailBrowser
|
||
|
||
Public Sub New(thumbnailBrowser As BetterThumbnailBrowser)
|
||
Me.thumbnailBrowser = thumbnailBrowser
|
||
End Sub
|
||
|
||
Private Function IComparer_Compare(itemA As BetterThumbnailBrowserItem, itemB As BetterThumbnailBrowserItem) As Integer Implements IComparer(Of BetterThumbnailBrowserItem).Compare
|
||
|
||
' get put visible item indices in sorted array
|
||
Dim visibleItems As ReadOnlyCollection(Of BetterListViewItem) = Me.thumbnailBrowser.VisibleItems
|
||
Dim visibleIndices As Integer() = New Integer(visibleItems.Count - 1) {}
|
||
|
||
For indexItem As Integer = 0 To visibleItems.Count - 1
|
||
visibleIndices(indexItem) = visibleItems(indexItem).Index
|
||
Next
|
||
|
||
Array.Sort(visibleIndices)
|
||
|
||
Dim valueA As Integer = (If((Array.BinarySearch(visibleIndices, itemA.Index) >= 0), 0, 1))
|
||
Dim valueB As Integer = (If((Array.BinarySearch(visibleIndices, itemB.Index) >= 0), 0, 1))
|
||
|
||
' compare items according to their visibility
|
||
Dim result As Integer = valueA.CompareTo(valueB)
|
||
|
||
If result <> 0 Then
|
||
Return result
|
||
End If
|
||
|
||
' compare items according to their indices
|
||
valueA = itemA.Index
|
||
valueB = itemB.Index
|
||
|
||
Return valueA.CompareTo(valueB)
|
||
End Function
|
||
|
||
End Class</code></pre>
|
||
|
||
|
||
<h2>Automatic Restaring on Scroll, Resize and Thumbnail Zoom</h2>
|
||
|
||
|
||
<p>Sometimes we need to restart loading because of scrolling or
|
||
resizing the control, or when thumbnails are zoomed. In the above
|
||
example, we have loaded visible items first. When user scrolls the
|
||
control, this set of visible items changes and hence we would like to
|
||
restart loading.</p>
|
||
|
||
<p>For example, we load thumbnails only at the necessary resolution.
|
||
But when the user resizes the thumbnails, we need to reload them in
|
||
higher resolution.</p>
|
||
|
||
<p>Another case is that we use custom item loading order such that
|
||
visible items are loaded first. When user scrolls the control, the order
|
||
is changed and we need to restart loading.</p>
|
||
|
||
<p>This functionality is provided by Better Thumbnail Browser. You
|
||
only need to set the following boolean properties to
|
||
<span class="code">true</span>:</p>
|
||
|
||
<ul style="list-style:none">
|
||
<li>
|
||
<span class="code">LoadingProvider.RestartOnScroll</span><ul style="list-style:none"><li>
|
||
<p>Restart loading when the control is scrolled or
|
||
resized.</p>
|
||
</li></ul>
|
||
</li>
|
||
<li>
|
||
<span class="code">ImageLoadingProvider.RestartOnExpand</span><ul style="list-style:none"><li>
|
||
<p>Restart loading when thumbnails are enlarged in size.</p>
|
||
</li></ul>
|
||
</li>
|
||
</ul>
|
||
<h2>Safe Cross-threaded Operations</h2>
|
||
|
||
|
||
<p>Better Thumbnail Browser uses two mechanisms for thread
|
||
synchronization: <span class="code">Control.Invoke</span> and
|
||
<span class="code">Mutex</span>.</p>
|
||
|
||
<p>The <span class="code">Control.Invoke</span> is used in
|
||
<span class="code">LoadingProvider.LoadItem</span> method. Here a
|
||
<span class="code">BetterThumbnailBrowser</span> instance is used as an synchronization
|
||
object, then <span class="code">LoadItemSync</span> is called so that images and other
|
||
data can be set to items on UI thread.</p>
|
||
|
||
<p><span class="code">Mutex</span> is used whenever Better Thumbnail Browser works
|
||
with item data. When you work with items on both loader thread and UI
|
||
thread, use <span class="code">BetterThumbnailBrowserItem.SyncRoot</span> as the
|
||
synchronization object. Here is a sample of safely setting
|
||
<span class="code">Path</span> property of
|
||
<span class="code">BetterThumbnailBrowserItem</span>:</p>
|
||
|
||
<p><strong>C#</strong></p>
|
||
<pre class="prettyprint"><code class="lang-cs">lock (item.SyncRoot)
|
||
{
|
||
item.Path = path;
|
||
}</code></pre>
|
||
|
||
<p><strong>Visual Basic</strong></p>
|
||
<pre class="prettyprint"><code class="lang-vb">SyncLock item.SyncRoot
|
||
item.Path = path
|
||
End SyncLock</code></pre>
|
||
|
||
|
||
<h2>
|
||
<a name="multi-pass-loading" id="multi-pass-loading"></a>Multi-pass Loading</h2>
|
||
|
||
|
||
<p>In case you need to load items in multiple sweeps, you can set
|
||
multiple instances of <span class="code">LoadingProvider</span> in the
|
||
<span class="code">LoadingProviders</span> property. The
|
||
<strong><em>MultiPassLoadingSample</em></strong> uses several instances of a
|
||
custom loading provider, each with different image quality setting. The
|
||
result is that paimages are loaded in successively higher levels of
|
||
detail:</p>
|
||
|
||
<p class="images"><img src="loading-multipass.png"></p>
|
||
|
||
<p>You can in which pass any item currently resides by reading the
|
||
<span class="code">BetterThumbnailBrowserItem.PassIndex</span> property. When item
|
||
loading is restarted, the items are loaded from their current pass. To
|
||
load all items again from scratch, set the <span class="code">PassIndex</span> property
|
||
to <span class="code">0</span> and then restart item loading.</p>
|
||
|
||
<br><div class="banner">
|
||
<a href="../../../better-thumbnail-browser.html"><img src="../resources/better-thumbnail-browser-overview.gif" alt="Better Thumbnail Browser" class="ss"></a>
|
||
<div class="inside">
|
||
<div class="text">Better Thumbnail Browser for .NET (C#, VB) - Image thumbnail viewing and loading control</div>
|
||
<span class="dbtn-c dbtn-hilight"><span class="dbtn-w"><a href="../../../betterthumbnailbrowser.exe" class="dbtn">Download</a></span></span>
|
||
<span class="dbtn-c"><span class="dbtn-w"><a href="../../../better-thumbnail-browser.html" class="dbtn">More Info</a></span></span>
|
||
</div>
|
||
</div>
|
||
<table class="navigation"><tr>
|
||
<td class="navigation-previous"><a href="chapter-layout.html"><strong>
|
||
« Layout</strong></a></td>
|
||
<td class="navigation-index"><a href="../../../better-thumbnail-browser/documentation.html"><strong>Index</strong></a></td>
|
||
<td class="navigation-next"><a href="chapter-text-formatting.html"><strong>Text Formatting »
|
||
</strong></a></td>
|
||
</tr></table>
|
||
<br><table class="footer"><tr>
|
||
<td class="footer-title">Better Thumbnail Browser Documentation
|
||
</td>
|
||
<td class="footer-copyright">
|
||
Copyright © 2010-2012 <a href="../../../index.html" target="_blank">ComponentOwl.com</a>
|
||
</td>
|
||
</tr></table>
|
||
</div></body>
|
||
</html>
|