Foysal94
Foysal94

Reputation: 603

My WPF program will not run

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

Answers (3)

Trae Moore
Trae Moore

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

Aditya Patil
Aditya Patil

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

ajg
ajg

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

Related Questions