Hey all it has been a few years since I last worked on my WPF code and sadly I'm not remembering what all I did in order for it to work as its coded.
The current issue I am facing is this:
An object of the type 'System.Windows.Media.ImageSourcesConverter' cannot be applied to a property that expects the type 'System.Windows.Data.IValueConverter'.
It has the above error on this line of code:
<Image Source="{Binding Path, Converter={StaticResource ImageSourceConverter}}" Stretch="Fill" />
The full XAML code being:
<Window.Resources> <!-- List of supported animations --> <FluidKit:SlideTransition x:Key="SlideTransition" x:Shared="False"/> <FluidKit:CubeTransition x:Key="CubeTransition" Rotation="BottomToTop" x:Shared="False"/> <FluidKit:FlipTransition x:Key="FlipTransition" x:Shared="False"/> <local1:ImageSourceConverter x:Key="ImageSourceConverter"/> <!-- Data template for animations --> <DataTemplate x:Key="ItemTemplate" x:Shared="False"> <Image Source="{Binding Path, Converter={StaticResource ImageSourceConverter}}" Stretch="Fill"/> </DataTemplate> </Window.Resources> <Grid x:Name="imageAreas" HorizontalAlignment="Left" Height="1920" Margin="0,0,0,0" VerticalAlignment="Top" Width="1080" ScrollViewer.VerticalScrollBarVisibility="Disabled"> <Grid HorizontalAlignment="Left" Height="726" VerticalAlignment="Top" Width="1080" x:Name="topGrid"> <FluidKit:TransitionPresenter RestDuration="0:0:3" IsLooped="True" Transition="{StaticResource FlipTransition}" ItemsSource="{Binding Images1}" Width="357" Height="272" HorizontalAlignment="Left" VerticalAlignment="Top" ItemTemplate="{StaticResource ItemTemplate}" x:Name="box1" Margin="0,0,0,454"/> <FluidKit:TransitionPresenter RestDuration="0:0:3" IsLooped="True" Transition="{StaticResource FlipTransition}" ItemsSource="{Binding Images2}" Width="357" Height="272" HorizontalAlignment="Left" VerticalAlignment="Top" ItemTemplate="{StaticResource ItemTemplate}" x:Name="box2" Margin="357,0,0,0"/> ....ETC....
It is references what I believe is this class (ImageSourceConverter.cs):
/// <summary> /// This converter automatically disposes image streams as soon as images /// are loaded, thus avoiding file access exceptions when attempting to delete images. /// </summary> public sealed class ImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string path = value as string; if (path != null) { //create new stream and create bitmap frame var bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.StreamSource = new FileStream(path, FileMode.Open, FileAccess.Read); //load the image now so we can immediately dispose of the stream bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); //clean up the stream to avoid file access exceptions when attempting to delete images bitmapImage.StreamSource.Dispose(); return bitmapImage; } else { return DependencyProperty.UnsetValue; } } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return DependencyProperty.UnsetValue; } }
My View Model (MainWindowViewModel.cs) is this:
public class MainWindowViewModel : IDisposable { private readonly IDisposable _token1; private readonly IDisposable _token2; private readonly IDisposable _token3; private readonly IDisposable _token4; private readonly IDisposable _token5; private readonly IDisposable _token6; private readonly IDisposable _token7; private readonly IDisposable _token8; private readonly IDisposable _token9; private readonly IDisposable _token10; public MainWindowViewModel(IImageSource imageSource) { // subscribe to update images at regular intervals _token1 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box1")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box1), ex => ShowError(ex)); _token2 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box2")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box2), ex => ShowError(ex)); _token3 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box3")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box3), ex => ShowError(ex)); _token4 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box4")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box4), ex => ShowError(ex)); _token5 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box5")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box5), ex => ShowError(ex)); _token6 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box6")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box6), ex => ShowError(ex)); _token7 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box7")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box7), ex => ShowError(ex)); _token8 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box8")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box8), ex => ShowError(ex)); _token9 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box9")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box9), ex => ShowError(ex)); _token10 = imageSource .GetImages(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "box10")) .ObserveOn(DispatcherScheduler.Current) .Subscribe(i => UpdateImages(i, box10), ex => ShowError(ex)); } private void ShowError(Exception ex) { MessageBox.Show(ex.Message, "Photo Gallery", MessageBoxButton.OK, MessageBoxImage.Error); } /// <summary> /// Updates the animation's images. /// </summary> /// <param name="images">The images to update with</param> /// <param name="animation">The animation to update</param> private void UpdateImages(IEnumerable<string> images, ObservableCollection<ImageViewModel> animation) { animation.Clear(); foreach (var i in images) { animation.Add(new ImageViewModel { Path = i }); } } /// <summary> /// Gets or sets a collection of images used for the first animation. /// </summary> public ObservableCollection<ImageViewModel> box1 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the second animation. /// </summary> public ObservableCollection<ImageViewModel> box2 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the third animation. /// </summary> public ObservableCollection<ImageViewModel> box3 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the fourth animation. /// </summary> public ObservableCollection<ImageViewModel> box4 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the fifth animation. /// </summary> public ObservableCollection<ImageViewModel> box5 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the sixth animation. /// </summary> public ObservableCollection<ImageViewModel> box6 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the seventh animation. /// </summary> public ObservableCollection<ImageViewModel> box7 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the eighth animation. /// </summary> public ObservableCollection<ImageViewModel> box8 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the nineth animation. /// </summary> public ObservableCollection<ImageViewModel> box9 { get; set; } = new ObservableCollection<ImageViewModel>(); /// <summary> /// Gets or sets a collection of images used for the tenth animation. /// </summary> public ObservableCollection<ImageViewModel> box10 { get; set; } = new ObservableCollection<ImageViewModel>(); public void Dispose() { _token1.Dispose(); _token2.Dispose(); _token3.Dispose(); _token4.Dispose(); _token5.Dispose(); _token6.Dispose(); _token7.Dispose(); _token8.Dispose(); _token9.Dispose(); _token10.Dispose(); } }
The IImageSource.cs:
public interface IImageSource { IObservable> GetImages(string path); }
And lastly the ImageSource.cs:
public class ImageSource : IImageSource { TimeSpan _pollingInterval; public ImageSource(TimeSpan pollingInterval) { _pollingInterval = pollingInterval; } public IObservable<IEnumerable<string>> GetImages(string path) { if (!Directory.Exists(path)) { return Observable.Empty<IEnumerable<string>>(); } try { return Observable.Create<IEnumerable<string>>(observer => { return TaskPoolScheduler.Default.ScheduleAsync(async (ctrl, ct) => { for (; ; ) { if (ct.IsCancellationRequested) { break; } try { var images = Directory.GetFiles(path, "*.jpg"); observer.OnNext(images); } catch (Exception ex) { observer.OnError(ex); throw; } await ctrl.Sleep(_pollingInterval).ConfigureAwait(false); } }); }); } catch (Exception ex) { Console.WriteLine(ex.Message); return null; } } }
From what i can remember, It loads up the XAML page there and populates each box with images that corispond to a directory called c:\images\box1...10. But as the error at the top of this says I’m not able to do that even though the program still runs just fine - be it without the images of course.
Would be great if someone could tell me what I was up too ha back those many years.