Reputation: 603
I am making a simple picture viewer application where it gets all the images from a folder and I can look at them all switching between them by clicking Previous and Next buttons.
Whenever I run my program I get this error the call stack contains only external code
. I have googled it and tbh I really don't get what this error means at all, and right now I just want to fix it so my program can start. So can you guys look at my code and help me fix the problem?
Heres the XAML for the window
<Window x:Class="PictureViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="700">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Button Name="button_Previous" Margin="0,0,10,5" HorizontalAlignment="Left" Width="75" Height="Auto" DockPanel.Dock="Left" Content="Previous" Click="button_Previous_Click" />
<Button Name="button_Next" Margin="0,0,10,5" HorizontalAlignment="Left" Width="75" Height="Auto" DockPanel.Dock="Left" Content="Next" Click="button_Next_Click" />
<Button Name="button_Browse" Margin="0,0,10,5" HorizontalAlignment="Left" Width="75" Height="Auto" DockPanel.Dock="Left" Content="Browse" />
</DockPanel>
<Rectangle Grid.Row="1" Fill="LightBlue" />
<Image Grid.Row="1" Margin="15" Name="image_Picture" Stretch="Fill" />
</Grid>
</Window>
The code behind the window:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace PictureViewer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
cPicture Picture;
public MainWindow()
{
InitializeComponent();
Picture = new cPicture();
Picture.Initialize();
DisplayPicture();
}
private void button_Previous_Click(object sender, RoutedEventArgs e)
{
Picture.Previous();
DisplayPicture();
}
private void button_Next_Click(object sender, RoutedEventArgs e)
{
Picture.Next();
DisplayPicture();
}
private void DisplayPicture()
{
BitmapImage image = new BitmapImage(new Uri(Picture.PictureList[Picture.CurrentPictureNumber]));
image_Picture.Source = image;
}
}
}
Also my Picture class:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PictureViewer
{
class cPicture
{
List<string> pictureList;
int currentPictureNumber = 0;
public List<string> PictureList
{
get { return pictureList; }
set { pictureList = value; }
}
public int CurrentPictureNumber
{
get { return currentPictureNumber; }
}
public void Initialize()
{
Directory.GetFiles(@"C:\Users\Syeda\Desktop\Photos");
List<string> pictureList = new List<string>(Directory.GetFiles(@"C:\Users\Syeda\Desktop\Photos"));
}
public void Next()
{
currentPictureNumber = currentPictureNumber + 1;
if (currentPictureNumber > pictureList.Count)
{
currentPictureNumber = 0;
}
}
public void Previous()
{
currentPictureNumber = currentPictureNumber - 1;
if (currentPictureNumber < 0)
{
currentPictureNumber = pictureList.Count;
}
}
}
}
Upvotes: 0
Views: 352
Reputation: 1787
here is a working implementation of what you were trying to accomplish. I utilized the MVVM Pattern. Typically when building small WPF applications this simplifies a lot of the work that needs to be done behind the scene. Enjoy :)
PicureViewer Class:
namespace Stack
{
public class PictureViewer : INotifyPropertyChanged
{
private const string PictureDirectory = @"C:\Users\TMoore\Pictures";
public int CurrentPictureNumber { get; set; }
private string currentImagePath;
public string CurrentImagePath
{
get { return currentImagePath; }
set
{
currentImagePath = value;
OnPropertyChanged();
}
}
private IList<string> pictureList { get; set; }
public IList<string> PictureList
{
get { return pictureList ?? (pictureList = new List<string>()); }
set { pictureList = value; }
}
public PictureViewer()
{
// you should add a search pattern
pictureList = Directory.EnumerateFiles(PictureDirectory)
.ToList();
CurrentImagePath = pictureList[0];
}
public void Next()
{
CurrentImagePath = CurrentPictureNumber > pictureList.Count() - 1
? PictureList[0]: PictureList[CurrentPictureNumber++];
}
public void Previous()
{
CurrentImagePath = CurrentPictureNumber == 0
? PictureList[PictureList.Count()-1] : PictureList[CurrentPictureNumber--];
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
XAML:
<Window x:Class="Stack.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Button Name="button_Previous" Margin="0,0,10,5" HorizontalAlignment="Left" Width="75" Height="Auto" DockPanel.Dock="Left" Content="Previous" Click="button_Previous_Click" />
<Button Name="button_Next" Margin="0,0,10,5" HorizontalAlignment="Left" Width="75" Height="Auto" DockPanel.Dock="Left" Content="Next" Click="button_Next_Click" />
<Button Name="button_Browse" Margin="0,0,10,5" HorizontalAlignment="Left" Width="75" Height="Auto" DockPanel.Dock="Left" Content="Browse" />
</DockPanel>
<Rectangle Grid.Row="1" Fill="LightBlue" />
<Image Grid.Row="1" Margin="15" Source="{Binding CurrentImagePath, UpdateSourceTrigger=PropertyChanged}" Stretch="Fill" />
</Grid>
</Window>
Code Behind:
public partial class MainWindow : Window
{
PictureViewer viewer { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = viewer ?? (viewer = new PictureViewer());
}
private void button_Previous_Click(object sender, RoutedEventArgs e)
{
viewer.Previous();
}
private void button_Next_Click(object sender, RoutedEventArgs e)
{
viewer.Next();
}
}
Upvotes: 2
Reputation: 558
For starters:
public void Initialize()
{
Directory.GetFiles(@"C:\Users\Syeda\Desktop\Photos");
List<string> pictureList = new List<string>(Directory.GetFiles(@"C:\Users\Syeda\Desktop\Photos"));
}
You are creating a local variable pictureList which overrides your member declaration. This method should be:
public void Initialize()
{
pictureList = new List<string>(Directory.GetFiles(@"C:\Users\Syeda\Desktop\Photos"));
}
Also, look at the picturelist in debug and see the files that get added on. For starters I suggest adding "*.jpg". This will ensure that only the jpg files paths are added to pictureList. So now the above method will look like this:
public void Initialize()
{
pictureList = new List<string>(Directory.GetFiles(@"C:\Users\Syeda\Desktop\Photos"), "*.jpg");
}
Also, the check code should compare with ">=" like this:
public void Next()
{
currentPictureNumber = currentPictureNumber + 1;
if (currentPictureNumber >= pictureList.Count)
{
currentPictureNumber = 0;
}
}
Same goes for the Previous method:
public void Previous()
{
currentPictureNumber = currentPictureNumber - 1;
if (currentPictureNumber < 0)
{
currentPictureNumber = pictureList.Count - 1;
}
}
Upvotes: 0
Reputation: 1753
pictureList is a local variable in your Initialise method - so the Global PictureList will always be empty
change Initialise to
public void Initialize()
{
pictureList = new List<string>(Directory.GetFiles(@"C:\Users\Syeda\Desktop\Photos"));
}
(also no point doing the redundant GetFiles line first)
Upvotes: 0