The last item on our to-do list is allowing the user to change the path of the picture files. WPF itself doesn’t have built-in dialog box classes to manage this, but the System.Windows.Forms
namespace has just what we need: the FolderBrowserDialog
class. This is launched from within the event handler for our FolderOpenMenuItem Click
event.
private void FolderOpenMenuItem_Click(object sender, RoutedEventArgs e)
{
SetPath();
}
private void SetPath()
{
FolderBrowserDialog dlg = new FolderBrowserDialog();
dlg.ShowDialog();
_path = dlg.SelectedPath;
ResetList();
}
When a user selects a folder, we update our internal field appropriately, reload the DirectoryImageList
class with the new path, and then reset our window’s DataContext
property to reflect the change. This is a perfect example of how seamless it is to use other .NET technologies and class libraries from within WPF. By adding the appropriate namespace and reference to our project, we just instantiate this class like any other class in our solution.
Tip
Because there are a fair number of controls that share the same name between WPF and WinForms (the ListBox control is one example), if you find yourself using classes from the System.Windows.Controls
and the System.Windows.Forms
libraries, you inevitably need to fully qualify some of your object names to avoid operating against the wrong class.
And with that, the application is functionally complete. For reference, we have provided the current state of the XAML and the code-behind listings in Listing 21.3 and Listing 21.4, respectively. If you really want to dissect this application, however, you should download the source code from this book’s website. This enables you to see the improvements made with graphics resources and general look and feel, producing the final polished version shown in Figure 21.31.
<Window x:Class="WpfImageViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Image Viewer Sample Application"
Height="400" Width="550"
Background="{DynamicResource BackgroundGradientBrush}">
<Window.Resources>
<DataTemplate x:Key="ImageDataTemplate">
<Image Source="{Binding UriSource.LocalPath}"
Width="125" Height="125" />
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox Grid.Row="1"
HorizontalAlignment="Stretch"
Margin="5" Name="listBox1"
VerticalAlignment="Stretch"
Width="175"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ImageDataTemplate}"
SelectionChanged="listBox1_SelectionChanged" />
<Menu Grid.ColumnSpan="2"
Background="{DynamicResource MenuBackgroundGradientBrush}"
HorizontalAlignment="Stretch"
Margin="0"
Name="menu1"
VerticalAlignment="Stretch">
<MenuItem Header="_Folder"
VerticalAlignment="Center">
<MenuItem x:Name="OpenMenuItem"
Header="_Open"
Click="FolderOpenMenuItem_Click"
VerticalAlignment="Center">
</MenuItem>
</MenuItem>
</Menu>
<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.Row="0"
Name="image1"
Stretch="UniformToFill"
Margin="5"
VerticalAlignment="Center"
HorizontalAlignment="Center" />
<StackPanel Grid.Row="1" Orientation="Horizontal"
HorizontalAlignment="Center" >
<Button Name="buttonBandW"
Style="{DynamicResource BWImageButtonStyle}"
Click="buttonBandW_Click"
Width="50"
Height="50"
Margin="10" />
<Button Name="buttonBlur"
Style="{DynamicResource BlurImageButtonStyle}"
Click="buttonBlur_Click"
Width="50"
Height="50"
Margin="10" />
<Button Name="buttonRotate"
Style="{DynamicResource RotateImageButtonStyle}"
Click="buttonRotate_Click"
Width="50"
Height="50"
Margin="10" />
<Button Name="buttonFlip"
Style="{DynamicResource FlipImageButtonStyle}"
Click="buttonFlip_Click"
Width="50"
Height="50"
Margin="10" />
</StackPanel>
</Grid>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfImageViewer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Private fields
private DirectoryImageList _imgList;
private string _path =
Environment.GetFolderPath(
Environment.SpecialFolder.MyPictures);
#endregion
#region Ctor
public MainWindow()
{
InitializeComponent();
ResetList();
this.DataContext = _imgList.Images;
}
#endregion
#region Event handlers and delegates
private void FolderOpenMenuItem_Click
(object sender, RoutedEventArgs e)
{
SetPath();
}
private void listBox1_SelectionChanged
(object sender, SelectionChangedEventArgs e)
{
this.image1.Source = (BitmapSource)
((sender as ListBox).SelectedItem);
this.image1.Effect = null;
}
private void buttonBandW_Click
(object sender, RoutedEventArgs e)
{
BitmapSource img = (BitmapSource)image1.Source;
image1.Source =
new FormatConvertedBitmap
(img, PixelFormats.Gray16,
BitmapPalettes.Gray256, 1.0);
}
private void buttonBlur_Click
(object sender, RoutedEventArgs e)
{
if (image1.Effect != null)
{
//if blur is current effect, remove
image1.Effect = null;
}
else
{
//otherwise, add the blur effect to the image
image1.Effect = new BlurEffect();
}
}
private void buttonRotate_Click
(object sender, RoutedEventArgs e)
{
CachedBitmap cache =
new CachedBitmap((BitmapSource)image1.Source,
BitmapCreateOptions.None,
BitmapCacheOption.OnLoad);
image1.Source =
new TransformedBitmap(cache,
new RotateTransform(90));
}
private void buttonFlip_Click
(object sender, RoutedEventArgs e)
{
CachedBitmap cache =
new CachedBitmap((BitmapSource)image1.Source,
BitmapCreateOptions.None,
BitmapCacheOption.OnLoad);
ScaleTransform scale =
new ScaleTransform(-1, -1, image1.Source.Width / 2,
image1.Source.Height / 2);
image1.Source =
new TransformedBitmap(cache, scale);
}
#endregion
#region Implementation
private void SetPath()
{
System.Windows.Forms.FolderBrowserDialog dlg =
new System.Windows.Forms.FolderBrowserDialog();
dlg.ShowDialog();
_path = dlg.SelectedPath;
ResetList();
}
private void ResetList()
{
if (IsValidPath(_path))
{
_imgList = new DirectoryImageList(_path);
}
this.DataContext = _imgList.Images;
}
private bool IsValidPath(string path)
{
try
{
string folder =
System.IO.Path.GetFullPath(path);
return true;
}
catch
{
return false;
}
}
#endregion
}
}