I get this weird NullReferenceExcpetion, in a WPF application. I don't get this every time, even if I do same operation. Can anyone please explain the reason for this,
public class AmazonUrl
{
public string Url { get; set; }
}
public partial class MainWindow : Window
{
public ObservableCollection<AmazonUrl> AmazonUrlList { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
AmazonUrlList = new ObservableCollection<AmazonUrl>();
}
public List<string> getURLList()
{
List<string> urlList = new List<string>();
for(int i = 0; i < AmazonUrlList.Count; i++)
{
AmazonUrl url = AmazonUrlList[i];
if (url == null)
continue;
String str = url.Url.ToString().Trim();
if (str.Length > 0)
urlList.Add(str);
}
return urlList;
}
private void openMenuItem_Click(object sender, RoutedEventArgs e)
{
List<string> urlList = getURLList();//This is where exception occur
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "SCR File (.scr)|*.scr|All Files|*.*";
if (openFileDialog.ShowDialog() != true){ ... }
}
Note: After adding these lines I made lots of changes to the application, and recompiled several times. So this is not a problem with Build or Compiling
Edit: My stack trace can find from here, https://pastebin.com/2vyH1qah
I can't reproduce the error, it must be something with your collection. What does your collection look like?
This should fix the problem either way--
public partial class MainWindow : Window
{
private static object lockObj = new object(); //Add
...
public List<string> getURLList()
{
List<string> urlList = new List<string>();
for (int i = 0; i < AmazonUrlList.Count; i++)
{
Amazon url = new AmazonUrl(); // Add
url = AmazonUrlList[i]; // Update
...
private void openMenuItem_Click(object sender, RoutedEventArgs e)
{
lock (lockObj) // Add
{
List<string> urlList = getURLList(); //This is where exception occur
}
Related
I made an mp3 player in C#. If I select the songs at once, they automatically play one after the other, but when it comes to a song I added later, I get a "System.IndexOutOfRangeException" error. When I add music later, I want the song to play automatically one after the other, how can I do that?
string[] yol, dosya;
private void Btn_Muzik_Ekle_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
if (ofd.ShowDialog()==System.Windows.Forms.DialogResult.OK)
{
dosya = ofd.SafeFileNames;
yol = ofd.FileNames;
for (int x = 0; x < dosya.Length; x++)
{
Lb_Muzik_Listesi.Items.Add(dosya[x]);
}
}
}
private void Lb_Muzik_Listesi_SelectedIndexChanged(object sender, EventArgs e)
{
//This Is Where I Got The Error
OynatmaEkranı.URL = yol[Lb_Muzik_Listesi.SelectedIndex];
OynatmaEkranı.Ctlcontrols.play();
try
{
var file = TagLib.File.Create(yol[Lb_Muzik_Listesi.SelectedIndex]);
var bin = (byte[])(file.Tag.Pictures[0].Data.Data);
Pb_Muzik_Kapak.Image = Image.FromStream(new MemoryStream(bin));
}
catch
{
}
}
private void Zamanlayıcı_Tick(object sender, EventArgs e) //Timer
{
if (OynatmaEkranı.playState==WMPLib.WMPPlayState.wmppsPlaying)
{
Pb_Muzik.Maximum=(int)OynatmaEkranı.Ctlcontrols.currentItem.duration;
Pb_Muzik.Value = (int)OynatmaEkranı.Ctlcontrols.currentPosition;
try
{
Lbl_Muzik_Sure.Text = OynatmaEkranı.Ctlcontrols.currentPositionString;
Lbl_Muzik_Bitis.Text = OynatmaEkranı.Ctlcontrols.currentItem
.durationString.ToString();
}
catch
{
}
}
if (Pb_Muzik.Value==Pb_Muzik.Maximum)
{
if (Lb_Muzik_Listesi.SelectedIndex<Lb_Muzik_Listesi.Items.Count-1)
{
Lb_Muzik_Listesi.SelectedIndex = Lb_Muzik_Listesi.SelectedIndex + 1;
}
}
}
You can avoid this problem managing your data in the ListBox. Create a class with your required info (the file and the name):
public class MuzikItem
{
public MuzikItem(string file)
{
this.Text = System.IO.Path.GetFileNameWithoutExtension(file);
this.Url = file;
}
public string Text { get; set; }
public string Url { get; set; }
public override string ToString()
{
// This is the text to show in ListBox
return this.Text;
}
}
Add items to the ListBox using this class:
foreach (var file in ofd.FileNames)
{
var item = new MuzikItem(file);
Lb_Muzik_Listesi.Items.Add(item);
}
And use it:
var item = Lb_Muzik_Listesi.SelectedItem as MuzikItem;
if (item != null)
{
OynatmaEkranı.URL = item.Url;
OynatmaEkranı.Ctlcontrols.play();
try
{
var file = TagLib.File.Create(item.Url);
var bin = (byte[])file.Tag.Pictures[0].Data.Data;
Pb_Muzik_Kapak.Image = Image.FromStream(new MemoryStream(bin));
}
catch
{
}
}
You try to get the selected item as a MuzikItem (all your items are of this class so this return null only when no item is selected) and with this, you have the Url.
UPDATE
I like manage this things with events. In your Ticks methods:
if (Pb_Muzik.Value == Pb_Muzik.Maximum)
{
OnSongFinished();
}
And create a method to manage this event:
private void OnSongFinished()
{
if (Lb_Muzik_Listesi.SelectedIndex < Lb_Muzik_Listesi.Items.Count - 1)
{
Lb_Muzik_Listesi.SelectedIndex = Lb_Muzik_Listesi.SelectedIndex + 1;
}
else
{
// Stop the player
OynatmaEkrani.Ctlcontrols.stop();
}
}
I am creating app with data base inside in windows forms and i don't know how to pass information through one class to another like here:
public partial class Form1 : Form
{
public Form1()
{
private void button1_Click(object sender, EventArgs e)
{
BazaDanychTabela BazaDanychTabelaVariable = new BazaDanychTabela();
string rejestracja = Rejestracja.ToString();
var dataoddania = dateTimePicker1.Value;
var kosztczescizamiennych = numericUpDown2.Value;
var pracamechanikawgodzinach = numericUpDown1.Value;
var index = MechanicyBox.SelectedIndex;
if (index < 0)
{
MessageBox.Show("Prosze Wybrac Mechanika");
}
else
{
var imie = ListC[index].Name;
var nazwisko = ListC[index].Nazwisko;
// this one I want to add
BazaDanych NowyLog = new BazaDanych(imie, nazwisko, rejestracja, dataoddania, kosztczescizamiennych, pracamechanikawgodzinach);
MessageBox.Show("Nowy log zostal utworzony!");
}
}
}
}
And here is the other class:
public partial class BazaDanychTabela : Form
{
public List<BazaDanych> Logi = new List<BazaDanych>();
}
And I want to add "NowyLog" to "Logi" how?
so what i would like to is setting back some attributes after an Custom Event is finished.
Scenario i have a save BackupDrives Class that does collection of data and then offers a Event to be called after its done.
Changing object properties can be done by button click, what i would like is to set them back to the same value after the event is finished.
Button click does the thing :
private void bbdrives_Click(object sender, RoutedEventArgs e)
{
backup.SaveDrives += OnSavingDrives;
backup.DrivesSave();
Drive_text.Visibility = Visibility.Visible;
drives_progres.Visibility = Visibility.Visible;
drives_progres.IsIndeterminate = true;
}
Now the triggered event method is not able to change the properties back.
private void OnSavingDrives(object sender, DrivesEventArgs e)
{
Directory.CreateDirectory(....);
File.WriteAllLines(e.Something, e.List2ToSave);
File.WriteAllLines(e.Something_lse, e.List1ToSave);
Drive_text.Visibility = Visibility.Collapsed;
drives_progres.Visibility = Visibility.Collapsed;
drives_progres.IsIndeterminate = false;
}
How do i do this. Since this does not work.
And on other thig here to - when i run the GUI i need to click 2 times one the same button to start it all. Done Code Clean + Rebuild. Still the same.
---EDIT---
As for code here you go.
This is a Class for collecting method and event.
public class DrivesEventArgs : EventArgs
{
string MYDOC = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
const string backup_Drives = "....";
const string backup_Letters = "...";
public List<string> List1ToSave = new List<string>();
public List<string> List2ToSave = new List<string>();
public string SAVE_DRIVE_Letter
{
get
{
string name = Path.Combine(MYDOC, backup_Letters);
return name;
}
}
public string SAVE_DRIVE_Path
{
get
{
string name = Path.Combine(MYDOC, backup_Drives);
return name;
}
}
}
public class DrivesBackup
{
private const string path = "Network";
private List<string> drives_to_save = new List<string>();
private List<string> letters_for_drives = new List<string>();
private RegistryKey reg1, reg2;
public event EventHandler<DrivesEventArgs> SaveDrives;
public void DrivesSave()
{
var data = new DrivesEventArgs();
try
{
if (drives_to_save.Count == 0)
{
reg1 = Registry.CurrentUser.OpenSubKey(path);
string[] mounted_drives = reg1.GetSubKeyNames();
foreach (var drive in mounted_drives)
{ //get all UNC Paths from mounted_drives
string[] getUNC = { path, drive };
string fullUNC = Path.Combine(getUNC);
reg2 = Registry.CurrentUser.OpenSubKey(fullUNC);
string UNCPath = reg2.GetValue("RemotePath").ToString(); //getting UNC PATH
Console.WriteLine(UNCPath);
data.List1ToSave.Add(drive.ToString());
data.List2ToSave.Add(UNCPath);
OnSaveDrives(data);
}
}
}
catch (Exception er)
{
throw er;
}
}
protected virtual void OnSaveDrives(DrivesEventArgs eD)
{
SaveDrives?.Invoke(this, eD);
}
Now here is the MAINWINDOW WPF
public partial class MainWindow : Window
{
DrivesBackup backup = new DrivesBackup();
public MainWindow()
{
InitializeComponent();
}
private void bbdrives_Click(object sender, RoutedEventArgs e)
{
backup.DrivesSave();
backup.SaveDrives += OnSavingDrives;
Drive_text.Visibility = Visibility.Visible;
drives_progres.Visibility = Visibility.Visible;
drives_progres.IsIndeterminate = true;
}
private void OnSavingDrives(object sender, DrivesEventArgs e)
{
Directory.CreateDirectory(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), #"SEG-Backup"));
File.WriteAllLines(e.SAVE_DRIVE_Path, e.List2ToSave);
File.WriteAllLines(e.SAVE_DRIVE_Letter, e.List1ToSave);
Drive_text.Visibility = Visibility.Collapsed;
drives_progres.Visibility = Visibility.Collapsed;
drives_progres.IsIndeterminate = false;
}
}
Now i do hope this would make some things more clear.
I know this is asked before, but I can't seem to figure it out.
I have a class which makes a list from a datagridview. I want to do stuff with this list in another class but I cant't access it. I can access it from Form1.cs like the code underneath. How do I access the list from a random class like I can in Form1.cs?
//Opens the file dialog and assigns file path to Textbox
OpenFileDialog browseButton = new OpenFileDialog();
private void browse_Click(object sender, EventArgs e)
{
browseButton.Filter = "Excel Files |*.xlsx;*.xls;*.xlsm;*.csv";
if (browseButton.ShowDialog() == DialogResult.OK)
{
ExcelPath.Text = browseButton.FileName;
fileExcel = ExcelPath.Text;
//SetAttributeValue(ExcelPath, fileExcel);
//nylp();
/*
////IMPORTERER 10TAB-DATA FRA EXCEL TIL DATAGRIDVIEW////
tenTabLine.fileExcel = fileExcel;
tenTabLine.tenTab(tenTabDgv);
*/
////IMPORTERER NYLPDATA TIL DATAGRIDVIEW////
nylpLine.fileExcel = fileExcel;
nylpLine.nylpData(nylpDgv);
////TAR DATA I NYLPDGV DATAGRIDVIEW OG BEREGNER VERTIKALE ELEMENTER////
vertElementer.vertBueDGV(nylpDgv, vertElementerDgv);
GetVertElementasList getList = new GetVertElementasList();
var TEST = getList.vertList(vertElementerDgv);
MessageBox.Show(TEST[5].p2.ToString());
}
else return;
}
When I try to do something like this I get lot of errors in Error List:
class GetKoord
{
GetVertElementasList getList = new GetVertElementasList();
var TEST = getList.vertList(vertElementerDgv);
MessageBox.Show(TEST[5].p2.ToString());
}
This is my list class
class GetVertElementasList
{
private List<vertEl> vertElementList = new List<vertEl>();
public List<vertEl> vertList(DataGridView VertElementer)
{
for (int i = 0; i<VertElementer.Rows.Count - 1; i++)
{
vertElementList.Add(new vertEl
{
elNr = (int)VertElementer.Rows[i].Cells[0].Value,
p1 = (double)VertElementer.Rows[i].Cells[1].Value,
p2 = (double)VertElementer.Rows[i].Cells[2].Value,
z1 = (double)VertElementer.Rows[i].Cells[3].Value,
z2 = (double)VertElementer.Rows[i].Cells[4].Value,
heln1 = Convert.ToDouble(VertElementer.Rows[i].Cells[5].Value),
heln2 = (double)VertElementer.Rows[i].Cells[6].Value
});
}
return vertElementList;
}
}
public class vertEl
{
private int _elNr;
private double _p1;
private double _p2;
private double _z1;
private double _z2;
private double _nylpRad;
private double _heln1;
private double _heln2;
public int elNr
{
get { return _elNr; }
set { _elNr = value; }
}
public double p1
{
get { return _p1; }
set { _p1 = value; }
}
public double p2
{
get { return _p2; }
set { _p2 = value; }
}
public double z1
{
get { return _z1; }
set { _z1 = value; }
}
public double z2
{
get { return _z2; }
set { _z2 = value; }
}
public double nylpRad
{
get { return _nylpRad; }
set { _nylpRad = value; }
}
public double heln1
{
get { return _heln1; }
set { _heln1 = value; }
}
public double heln2
{
get { return _heln2; }
set { _heln2 = value; }
}
}
EDIT:
I've made it work now except that I get a out of range exception.
class code is:
class GetKoord
{
public GetVertElementasList getList = new GetVertElementasList();
BridgGeometry obj = new BridgGeometry();
public void foo()
{
var TEST = getList.vertList(obj.vertElementerDgv);
MessageBox.Show(TEST[2].elNr.ToString());
}
}
In form1 or BridgGeometry as it is called in my project I have which is giving me out of range exception.
GetKoord getZ = new GetKoord();
getZ.foo();
EDIT2:
The code underneath works and gives a message box with some value in list. But the method foo() in class above gives a out of range error.
private void browse_Click(object sender, EventArgs e)
{
browseButton.Filter = "Excel Files |*.xlsx;*.xls;*.xlsm;*.csv";
if (browseButton.ShowDialog() == DialogResult.OK)
{
////TESTING////WORKING CODE AND GIVES A MESSAGEBOX WITH VALUE
GetVertElementasList getVertList = new GetVertElementasList();
var TEST = getVertList.vertList(vertElementerDgv);
MessageBox.Show(TEST[2].elNr.ToString());
}
else return;
}
I think you are trying to access the variable directly in the class; which will not work. Try following
class GetKoord
{
GetVertElementasList getList = new GetVertElementasList();
public void foo()
{
var TEST = getList.vertList(vertElementerDgv);
MessageBox.Show(TEST[5].p2.ToString());
}
}
I tested your code and it seemed to worked. My code for you and #Anand
No Errors, except for empty Lists. But thats because I didn't fed it any information. So, there shouldn't be a problem.
#Grohl maybe try my code and comment where the error is displayed. This should be the most easy way to find the problem.
TestClass which represents class GetKoord
namespace TestForm
{
class TestClass
{
public TestClass()
{
DataGridView tmp = new DataGridView();
GetVertElementasList getList = new GetVertElementasList();
var TEST = getList.vertList(tmp);
MessageBox.Show(TEST[5].p2.ToString());
}
}
}
The GetVertElementasList
namespace TestForm
{
class GetVertElementasList
{
private List<vertEl> vertElementList = new List<vertEl>();
public List<vertEl> vertList(DataGridView VertElementer)
{
for (int i = 0; i < VertElementer.Rows.Count - 1; i++)
{
vertElementList.Add(new vertEl
{
elNr = (int)VertElementer.Rows[i].Cells[0].Value,
p1 = (double)VertElementer.Rows[i].Cells[1].Value,
p2 = (double)VertElementer.Rows[i].Cells[2].Value,
z1 = (double)VertElementer.Rows[i].Cells[3].Value,
z2 = (double)VertElementer.Rows[i].Cells[4].Value,
heln1 = Convert.ToDouble(VertElementer.Rows[i].Cells[5].Value),
heln2 = (double)VertElementer.Rows[i].Cells[6].Value
});
}
return vertElementList;
}
}
//Some other stuff
}
Last but not least. the code from the button click event:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
DataGridView tmp = new DataGridView();
GetVertElementasList getList = new GetVertElementasList();
var TEST = getList.vertList(tmp);
MessageBox.Show(TEST[5].p2.ToString());
TestClass tmpClass = new TestClass();
}
}
To #Grohl EDIT2:
It hurts to see that you are trying to read data without checking if there is any. In such cases, check!
Like this:
if(TEST.Count() >= 3)
{
MessageBox.Show(TEST[2].elNr.ToString());
}
It should debug at be smooth at runtime. I think your problem is getting the data.
Make sure you load the needed data and check if it isn't null.
I am working on a problem where I load a text file into a string list and display in a listbox (which I have done) but I now want a button event to place the contents of the list in a second listbox which is just coming up blank. I can easily do this in VB but I'm fairly new to C# and realise I am probably missing something obvious.
namespace texttoarray
{
public partial class Form1 : Form
{
public int counter;
public List<string> finalList;
public Form1()
{
InitializeComponent();
List<string> finalList = AddToList();
}
public List<string> AddToList()
{
counter = 0;
string line;
List<string> list = new List<string>();
System.IO.StreamReader file = new System.IO.StreamReader(#"list.txt");
while ((line = file.ReadLine()) != null)
{
listBox1.Items.Add(line);
list.Add(line);
counter++;
}
//listBox2.DataSource = list;
MessageBox.Show(counter.ToString());
return list;
}
public void button1_Click(object sender, EventArgs e)
{
listBox2.DataSource = finalList;
}
}
}
You are creating a local list in constructor. You should assign result of AddToList method to field finalList.
Your code:
List<string> finalList;
public Form1()
{
InitializeComponent();
List<string> finalList = AddToList(); //Creation of new local variable 'finalList'
}
Solution:
List<string> _finalList;
public Form1()
{
InitializeComponent();
_finalList = AddToList(); //Use '_finalList' field
}
Note: You could have easily detected this if you have used appropriate naming conventions. i.e. Private field names should start with underscore. Public instance variables should start with Capital letter.