I've been developing a MP3 player in WPF CSharp and when I add a mp3 file, it adds normally, but when I add another mp3 file separately the name of the newly added mp3 file is the same as the first added one here's my code:
private List<String> Files = new List<string> { };
private List<String> Paths = new List<string> { };
private void AddSong_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
if (ofd.ShowDialog() == true)
{
mediaPlayer.Stop();
for (int i = 0; i < ofd.FileNames.Length; i++)
{
Files.Add(System.IO.Path.GetFileNameWithoutExtension(ofd.FileNames[i]));
Paths.Add(ofd.FileNames[i]);
Playlist.Items.Add(Files[i]);
}
}
}
You're adding in Files[i], but i is not the right index to be using there. Instead, add in the most recent file, System.IO.Path.GetFileNameWithoutExtension(ofd.FileNames[i]).
(This is a problem when the Files is not empty when you add extra files, as you observed.)
private List<String> Files = new List<string> { };
private List<String> Paths = new List<string> { };
private void AddSong_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
if (ofd.ShowDialog() == true)
{
int InitialFilesLength = Files.Length;
mediaPlayer.Stop();
for (int i = 0; i < ofd.FileNames.Length; i++)
{
Files.Add(System.IO.Path.GetFileNameWithoutExtension(ofd.FileNames[i]));
Paths.Add(ofd.FileNames[i]);
Playlist.Items.Add(Files[i - InitialFilesLength]);
}
}
}
Related
I've managed to open a txt file to a ComboBox where it shown only the second element"100", and if I select one of the items in ComboBox will show me the the first element witch is "firstName", the problem is I want to modify the first element from the textbox and save it to the main file or new file on the way that I replace the old element with new one from the textbox and save the file as it was at the beginning
TXT FILE
firstName;;;100;;;0;
firstName;;;100;;;1;
firstName;;;100;;;2;
firstName;;;100;;;3;
firstName;;;0100;;;4;
firstName;;;0100;;;5;
firstName;;;0100;;;6;
firstName;;;0100;;;7;
lastName;;;0100;;;0;
lastName;;;0100;;;1;
lastName;;;0100;;;2;
lastName;;;0100;;;3;
lastName;;;0100;;;4;
lastName;;;0100;;;5;
lastName;;;0100;;;6;
lastName;;;0100;;;7;
i want to change the first elements from the textbox and replace it with user input and save the file as in it were,
example:
//output
john;;;100;;;0;
Patrick;;;100;;;1;
firstName;;;100;;;2;
namespace WindowsFormsApp8
{
public partial class Form1 : Form
{
public string[] lines;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = "txt file (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
//string[] lines = File.ReadAllLines(openFileDialog.FileName);
lines = File.ReadAllLines(openFileDialog.FileName);
List<string> result = new List<string>();
string[] par = new string[1];
par[0] = ";;;";
for (int i = 0; i < lines.Length; i++)
{
string[] row = lines[i].Split(par, StringSplitOptions.None);
if (row.Length > 2)
{
if (!result.Contains(row[1]))
result.Add(row[1]);
}
}
foreach (string line in result)
{
comboBox1.Items.Add(line);
}
}
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var d = lines;
var t = d.Where(g => g.Contains(comboBox1.Text));
string allItems = "";
foreach (string item in t)
{
string[] r = item.Split(new string[] { ";;;" }, StringSplitOptions.None);
allItems += r[0] + Environment.NewLine;
}
textBox1.Text = allItems;
}
}
}
I've read your code carefully and my understanding may not be perfect but it should be close enough that I can help. One way to achieve your objectives is with data binding and I'll demonstrate this step by step.
"open a txt file to a combobox"
In your main form, you'll move the OpenFileDialog so that it is now a member variable:
private OpenFileDialog openFileDialog = new OpenFileDialog
{
InitialDirectory = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Files"),
FileName = "Data.txt",
Filter = "txt file (*.txt)|*.txt|All files (*.*)|*.*",
FilterIndex = 2,
RestoreDirectory = true,
};
In the main form CTor
Handle event buttonLoad.Click to display the dialog
Handle event openFileDialog.FileOk to read the file.
The DataSource of comboBox will be set to the list of lines read from the file.
Initialize
public MainForm()
{
InitializeComponent();
buttonLoad.Click += onClickLoad;
openFileDialog.FileOk += onFileOK;
comboBox.DataSource = lines;
.
.
.
Disposed += (sender, e) => openFileDialog.Dispose();
}
BindingList<Line> lines = new BindingList<Line>();
private void onClickLoad(object? sender, EventArgs e) =>
openFileDialog.ShowDialog();
In a minute, we'll look at those three things step by step. But first...
Serialize and Deserialize
You have a lot of loose code doing string splits to decode your serializer format. Try consolidating this in a class that is also suitable to be used in a BindingList<Line>. This will be the data source of your combo box. Also consider using a standard serialization format like JSON instead!
class Line : INotifyPropertyChanged
{
// Make a Line from serialized like firstName;;;100;;;0;
public Line(string serialized)
{
// Convert to a stored array
_deserialized = serialized.Split(new string[] { ";;;" }, StringSplitOptions.None);
}
// Convert back to the format used in your file.
public string Serialized => string.Join(";;;", _deserialized);
private string[] _deserialized { get; } // Backing store.
// Convert a list of Lines to a collection of strings (e.g. for Save).
public static IEnumerable<string> ToAllLines(IEnumerable<Line> lines) =>
lines.Select(_ => _.Serialized);
// Determine how a Line will be displayed in the combo box (e.g. "0100").
public override string ToString() => _deserialized[1].ToString();
// Use array syntax to access elements of the split array.
public string this[int index]
{
get => _deserialized[index];
set
{
if(!Equals(_deserialized[index],value))
{
// Send event when any array value changes.
_deserialized[index] = value;
OnPropertyChanged($"{index}");
}
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Load
Once the data file is selected, the raw text file will be shown and the combo box will be populated.
private void onFileOK(object? sender, CancelEventArgs e)
{
lines.Clear();
foreach (var serialized in File.ReadAllLines(openFileDialog.FileName))
{
lines.Add(new Line(serialized));
}
textBoxMultiline.Lines = lines.Select(_=>_.Serialized).ToArray();
comboBox.SelectedIndex = -1;
}
Replacement
Going back to the main form CTor there are three more events we care about:
public MainForm()
{
.
.
.
comboBox.SelectedIndexChanged += onComboBoxSelectedIndexChanged;
textBoxEditor.TextChanged += onEditorTextChanged;
lines.ListChanged += onListChanged;
.
.
.
}
When a new item is selected in the combo box, put it in the text editor.
private void onComboBoxSelectedIndexChanged(object sender, EventArgs e)
{
var item = (Line)comboBox.SelectedItem;
if (item != null)
{
textBoxEditor.Text = item[0];
}
}
When the textEditor text changes, modify the item.
private void onEditorTextChanged(object? sender, EventArgs e)
{
var item = (Line)comboBox.SelectedItem;
if (item != null)
{
item[0] = textBoxEditor.Text;
}
}
When the item changes, update the file display in the big textbox.
private void onListChanged(object? sender, ListChangedEventArgs e)
{
switch (e.ListChangedType)
{
case ListChangedType.ItemChanged:
textBoxMultiline.Lines = lines.Select(_=>_.Serialized).ToArray();
break;
}
}
Save
SaveFileDialog saveFileDialog = new SaveFileDialog
{
InitialDirectory = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Files"),
FileName = "Data.txt",
Filter = "txt file (*.txt)|*.txt|All files (*.*)|*.*",
FilterIndex = 2,
RestoreDirectory = true,
};
private void onClickSave(object? sender, EventArgs e) =>
saveFileDialog.ShowDialog(this);
private void onSaveFileOK(object? sender, CancelEventArgs e)
{
File.WriteAllLines(saveFileDialog.FileName, Line.ToAllLines(lines));
}
I hope this is "close enough" to what you have described that if will give you some ideas to experiment with.
I'm trying to make a C# music player and to do so, I'm using the WMP object found in win forms, I got it to load files from an specific folder on the press of a button, however, I want it to load every media file (FLAC, mp3, wav...) in an specific folder and its sub folders.
by now the code I have to load files is as follows.
string[] path, files; //Global Variables to get the path and the file name
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
//This function displays the files in the path and helps selecting an index
axWindowsMediaPlayer1.URL = path[listBox1.SelectedIndex];
axWindowsMediaPlayer1.uiMode = "None";
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
if(ofd.ShowDialog() == DialogResult.OK)
{
//Function that loads the files into the list.
files = ofd.SafeFileNames;
path = ofd.FileNames;
for (int i = 0; i < files.Length; i++)
{
listBox1.Items.Add(files[i]);
}
}
}
Step 1: Use FolderBrowserDialog instead of OpenFileDialog, this helps you to select a folder instead of a file
Step 2: After selecting a file, You can use the method Directory.EnumerateFiles(Your_Path, ".", SearchOption.AllDirectories) to get all files in the selected folder.
Try this:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
axWindowsMediaPlayer1.URL = listBox1.Items[listBox1.SelectedIndex];
axWindowsMediaPlayer1.uiMode = "None";
}
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog FBD = new FolderBrowserDialog();
if (FBD.ShowDialog() == DialogResult.OK)
{
LoadFiles(FBD.SelectedPath, new string[] { ".mp3", ".wav" }); //You can add more file extensions...
}
}
private void LoadFiles(string FolderPath, string[] FileExtensions)
{
string[] Files = System.IO.Directory.GetFiles(FolderPath);
string[] Directories = System.IO.Directory.GetDirectories(FolderPath);
for (int i = 0; i < Directories.Length; i++)
{
LoadFiles(Directories[i], FileExtensions);
}
for (int i = 0; i < Files.Length; i++)
{
for (int j = 0; j < FileExtensions.Length; j++)
{
if (Files[i].ToLower().EndsWith(FileExtensions[j].ToLower()))
{
listBox1.Items.Add(Files[i]);
break;
}
}
}
}
So I have this listview and I can add items to it through a openfiledialog and then I do File.ReadLine and read through all the lines of the textfile I just selected.
So let's say I selected a textfile with 3 lines in it.
Bob
Cat
Human
then what it does is it adds the items to the listview.
Now for every item it adds I want to increment the label (add from 0 > 3).
private void btnAddItems_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Names|*.txt";
if(ofd.ShowDialog() == DialogResult.OK)
{
string[] recipients = File.ReadAllLines(ofd.FileName);
foreach(string name in recipients)
{
lvRecipient.Items.Add(name);
//increment the number of items in the list
foreach(int item in lvRecipient.Items)
{
int i = 0;
i++;
lbCount.Text = i.ToString();
}
}
}
I tried that but got an error as soon as I ran it, I was pretty sure it wouldnt work because there is no real locig behind it, how do I make my label increment from 0 > 3 (or how ever many items there are in the textfile)?
To solve the question that you asked, it can be done like this:
private void btnAddItems_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Names|*.txt";
if(ofd.ShowDialog() == DialogResult.OK)
{
string[] recipients = File.ReadAllLines(ofd.FileName);
foreach(var name in recipients)
{
lvRecipient.Items.Add(name);
lbCount.Text = lvRecipient.Items.Count.ToString();
}
}
}
It would be better to just set the count label after all the items were added, rather then setting it every time a new one is added because the adding operation should be very quick making it unlikely a human would even detect the changing number. This could be done like so:
private void btnAddItems_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Names|*.txt";
if(ofd.ShowDialog() == DialogResult.OK)
{
string[] recipients = File.ReadAllLines(ofd.FileName);
foreach(var name in recipients)
{
lvRecipient.Items.Add(name);
}
lbCount.Text = lvRecipient.Items.Count.ToString();
}
}
using System;
using System.IO;
using System.Windows.Forms;
namespace Jonny
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnAddItems_Click(object sender, EventArgs e)
{
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Names|*.txt";
if (ofd.ShowDialog() == DialogResult.OK)
{
string[] recipients = File.ReadAllLines(ofd.FileName);
foreach (string name in recipients)
{
lvRecipient.Items.Add(name);
//increment the number of items in the list
foreach (var item in lvRecipient.Items)
{
int i = 0;
i++;
lbCount.Text = i.ToString();
}
}
}
}
}
}
}
It does work - I tried it. If you just change the "int" to "var" - because the "lvRecipient.Items" is unable to be treated as an integer in the foreach loop.
this could be what you are looking, maybe someone will find it useful, my function is running async though and i had to to invoke the label.
delegate void SetTextCallback1(string name);
private void SetTextLabel(string name)
{
if (this.label1.InvokeRequired)
{
SetTextCallback1 d = new SetTextCallback1(SetTextLabel);
this.Invoke(d, new object[] { name });
}
else
{
this.label1.Text = name;
}
}
then i used task.run :
await Task.Run(() => SetTextLabel(name));
and of course the Task.Run line is inside a loop wrapped in an async func.
Initially I will be loading images(say 20 images) into a picturebox from a specified folder through selection from combobox dropdown, they get loaded normally into the picturebox.
The problem I am facing is when I select the next folder to acquire the image for processing, the previously selected folders images are also displayed in the picturebox after its count only the next folders images are displayed, I am unable to clear the previously loaded images.
To be specific, when I click on a folder from dropdown I want the particular folders image inside the picturebox I don't want the previously loaded images along with them. Am working in VS2013 with c#.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
ArrayList alist = new ArrayList();
int i = 0;
int filelength = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DirectoryInfo di = new DirectoryInfo(#"C:\Users\Arun\Desktop\scanned");
DirectoryInfo[] folders = di.GetDirectories();
comboBox1.DataSource = folders;
}
private void button7_Click(object sender, EventArgs e)
{
if (i + 1 < filelength)
{
pictureBox1.Image = Image.FromFile(alist[i + 1].ToString());
i = i + 1;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
private void button8_Click(object sender, EventArgs e)
{
if (i - 1 >= 0)
{
pictureBox1.Image = Image.FromFile(alist[i - 1].ToString());
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
i = i - 1;
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string selected = comboBox1.SelectedItem.ToString();
String fullpath = Path.Combine(#"C:\Users\Arun\Desktop\scanned", selected);
DirectoryInfo di1 = new DirectoryInfo(fullpath);
DirectoryInfo[] folders1 = di1.GetDirectories();
comboBox2.DataSource = folders1;
}
private void button9_Click(object sender, EventArgs e)
{
string selected1 = comboBox1.SelectedItem.ToString();
string selected2 = comboBox2.SelectedItem.ToString();
//Initially load all your image files into the array list when form load first time
System.IO.DirectoryInfo inputDir = new System.IO.DirectoryInfo(Path.Combine(#"C:\Users\Arun\Desktop\scanned", selected1, selected2)); //Source image folder path
try
{
if ((inputDir.Exists))
{
//Get Each files
System.IO.FileInfo file = null;
foreach (System.IO.FileInfo eachfile in inputDir.GetFiles())
{
file = eachfile;
if (file.Extension == ".tif")
{
alist.Add(file.FullName); //Add it in array list
filelength = filelength + 1;
}
else if(file.Extension == ".jpg")
{
alist.Add(file.FullName); //Add it in array list
filelength = filelength + 1;
}
}
pictureBox1.Image = Image.FromFile(alist[0].ToString()); //Display intially first image in picture box as sero index file path
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
i = 0;
}
}
catch (Exception ex)
{
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.D)
{
if (i + 1 < filelength)
{
pictureBox1.Image = Image.FromFile(alist[i + 1].ToString());
i = i + 1;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
else if(e.KeyCode == Keys.A)
{
if (i - 1 >= 0)
{
pictureBox1.Image = Image.FromFile(alist[i - 1].ToString());
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
i = i - 1;
}
}
}
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}
Your code has many issues.
The one you are looking for is that you don't clear the alist before loading new file names.
So insert:
alist.Clear();
before
//Get Each files
And also
filelength = alist.Count;
after the loop. No need to count while adding!
Also note that ArrayList is pretty much depracated and you should use the type-safe and powerful List<T> instead:
List<string> alist = new List<string>();
Of course a class variable named i is silly and you are also relying on always having a SelectedItem in the comboBox2.
And since you are not properly Disposing of the Image you are leaking GDI resources.
You can use this function for properly loading images:
void loadImage(PictureBox pbox, string file)
{
if (pbox.Image != null)
{
var dummy = pbox.Image;
pbox.Image = null;
dummy.Dispose();
}
if (File.Exists(file)) pbox.Image = Image.FromFile(file);
}
It first creates a reference to the Image, then clears the PictureBox's reference, then uses the reference to Dispose of the Image and finally tries to load the new one.
I want to add filenames (without the full path) to the ListBox.
The code below is working smoothly, but when when I change FileNames to SafeFileNames (for hiding item location) it's not working anymore.
XAML
<MediaElement x:Name="mePlayer" Margin="64,0,90,61"/>
<ListBox x:Name="listbox4" Background="Salmon" BorderBrush="Black" BorderThickness="3"/>
CS
private void load_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
ofd.DefaultExt = ".mp3";
ofd.Filter = "All|*.*";
ofd.Multiselect = true;
Nullable<bool> result = ofd.ShowDialog();
if (result == true)
{
for (int i = 0; i < ofd.FileNames.Length; i++)
{
listbox4.Items.Add(ofd.FileNames[i].ToString());
listbox4.SelectedItem = ofd.FileName;
mePlayer.Source = new Uri(
listbox4.SelectedItem.ToString(),
UriKind.RelativeOrAbsolute);
mePlayer.LoadedBehavior = MediaState.Play;
}
}
}
This code should work for you. Please read the comments in the code before you proceed.
private Dictionary<string, string> fileDictionary = new Dictionary<string, string>();
private void load_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
ofd.DefaultExt = ".mp3";
ofd.Filter = "All|*.*";
ofd.Multiselect = true;
Nullable<bool> result = ofd.ShowDialog();
if (result == true)
{
for (int i = 0; i < ofd.FileNames.Length; i++)
{
var filePath = ofd.FileNames[i];
var fileName = System.IO.Path.GetFileName(filePath);
fileDictionary.Add(fileName, filePath);
// not sure about this logic. You may need to reconsider what you are trying to do here.
//Instead of doing this, create a click event for the list box and get the selected file path to be played from the dictionary.
listbox4.Items.Add(fileName);
}
}
}
private void listbox4_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (listbox4.SelectedItem != null)
{
var selectedFile = listbox4.SelectedItem.ToString();
string selectedFilePath;
fileDictionary.TryGetValue(selectedFile, out selectedFilePath);
if (!string.IsNullOrEmpty(selectedFilePath))
{
mePlayer.Source = new Uri(selectedFilePath, UriKind.RelativeOrAbsolute);
mePlayer.LoadedBehavior = MediaState.Play;
}
}
}