How can I make the list on the right populate with only items which meet the search criteria? I'm not asking for the literal code necessarily, but just some general guidance on how to do so.
I've already written the code to populate the list on the left with C#, supplying a directory to populate the list from. I was just not clear on how to get the list to populate correctly when using the search field at the top.
Should I just call another function which researches the directory for the files based on the search criteria? or store the initial file list in a variable and search within that to populate the list?
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace directoryBrowser
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ListDirectory(treeView1, #"C:\Windows");
}
public void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
public static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
try
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
} catch {
// cannot access directory
}
}
foreach (var file in directoryInfo.GetFiles())
{
directoryNode.Nodes.Add(new TreeNode(file.Name));
}
return directoryNode;
}
}
}
Create a parent node that should be global to the form. so that you can use the parent node without searching the directory (folder) on the harddisk every time. lets say
var directoryNode = new TreeNode(directoryInfo.Name);
and add all the subsequent nodes to the directoryNode as your code already performing this. Finally you get the overall structure added to directoryNode. Add this directoryNode to the treeview. your treeview will be populated. when the user provides search parameter, search in the directoryNode not in the actual directory, in memory searching is fast then searching directory on the hardisk, and create list of nodes and assign to the treeview. when the search parameter is removed by the user assign the directoryNode again.
Hope this suggestion will help
Related
I am trying to build my own Music Player android app.
I want it to be very simple, just find all valid music files (perhaps I set file types such as mp3, m4a, wma etc for it to look for?) and play them in order of how they are found.
So far I have it so that I can find the default music folder path using
string musicDirectoryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMusic).ToString();
What I now need is to check every file (and folder) inside that folder to see if it is mp3/m4a etc and then add them to the list. I've been messing and trying some foreach loops but cannot get anything useful.
I am very confused and quite new to Android development.
As you will see, if I specify a song that I know is on my phone in the default directory (*/NewPipe/Intergalatic - Beastie.m4a), then the music is playing.
So, how can I get a List of all those strings such as the "NewPipe/Beastie.." etc (along with the other 500+ folders inside my default music directory?
Here is my entire class so far (it's the only class in the project):
using System;
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Support.V7.App;
using Android.Views;
using Android.Widget;
using Android.Media;
using Xamarin.Android;
using System.IO;
using System.Collections.Generic;
using Android.Util;
namespace Music_Player_v001
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected MediaPlayer mediaPlayer;
List<string> filepaths_audio = new List<string>();
public void StartMediaPlayer(String filePath)
{
mediaPlayer.Reset();
mediaPlayer.SetDataSource(filePath);
mediaPlayer.Prepare();
mediaPlayer.Start();
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
fab.Click += FabOnClick;
string musicDirectoryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMusic).ToString();
Log.Info("FILEPATHS: ", "music directory path is: " + musicDirectoryPath);
mediaPlayer = new MediaPlayer();
StartMediaPlayer(musicDirectoryPath + "/NewPipe/Intergalactic - Beastie Boys (HD).m4a");
//foreach(AudioTrack track in Android.OS.Environment.DirectoryMusic)
//{
// Log.Info("BULLSHIT TAG","track count =======================" + tracks);
// tracks++;
//}
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.menu_main, menu);
return true;
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
int id = item.ItemId;
if (id == Resource.Id.action_settings)
{
return true;
}
return base.OnOptionsItemSelected(item);
}
private void FabOnClick(object sender, EventArgs eventArgs)
{
View view = (View) sender;
Snackbar.Make(view, "Replace with your own action", Snackbar.LengthLong)
.SetAction("Action", (Android.Views.View.IOnClickListener)null).Show();
}
}
}
Additional
I also tried this:
foreach (File f in Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMusic))
{
}
It sounds like your main issue is recursively iterating through all the files in the directory and its subdirectories. Here are a few relevant links:
How to recursively list all the files in a directory in C#?
Best way to iterate folders and subfolders
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-iterate-through-a-directory-tree
The easiest approach is probably Directory.EnumerateFiles, used like this: Directory.EnumerateFiles(musicDirectoryPath, "*", SearchOption.AllDirectories) to ensure that it also enumerates through the sub-directories.
foreach (string musicFilePath in Directory.EnumerateFiles(musicDirectoryPath, "*", SearchOption.AllDirectories)) {
Log.Info("Music File", "Music file path is " + musicFilePath);
// do whatever you want to with the file here
}
Note that this may fail if there is an access-restricted directory (or some other error) somewhere in the tree. If you'd like your solution to work around this, see the links I posted above, particularly the bottom one.
Also note, you can change that "*" (wildcard) in the method call to "*.mp3" or "*.wav" or so on, to only match files with those extensions. However, as the method doesn't support regex, I don't think there's any way to match multiple file extensions (like BOTH mp3 and wav). I think you'd have to use the "*" and then just check within the foreach if the file is a valid music file.
What i want to do here was getting an string input from the user and if that string input is in the array i want to delete it from the file (all the items in the array is actual files in my computer that got scanned at the start of the program and become one array) is there a way to do that without foreach?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.Threading;
string typed = null;
string loc = AppDomain.CurrentDomain.BaseDirectory;
if (!Directory.Exists(loc + #"\shortcuts"))
{
Directory.CreateDirectory(loc + #"\shortcuts");
}
string[] directory = Directory.GetFiles(loc + #"\shortcuts");
foreach (var filed in directory)
{
File.Move(filed, filed.ToLowerInvariant());
}
string[] file = Directory.GetFiles(loc + #"\shortcuts").Select(System.IO.Path.GetFileNameWithoutExtension).ToArray();
foreach (string dir in directory)
{
}
if (typed == "exit") System.Environment.Exit(0);
//other ifs here
else if (typed == "rem")
{
//Console.WriteLine("\nNot available at the moment\n");
////add this command
Console.WriteLine("\nWhich program entry do you wish to erase?\n");
typed = Console.ReadLine().ToLower();
if (file.Any(typed.Contains))
{
File.Delete(file.Contains(typed)); //this is the broken part and i don't know how i can get the stings from there
Console.WriteLine("hi");
}
else Console.WriteLine("\n" + typed + " is not in your registered programs list.\n");
}
Expected result was getting rid of the typed program in the folder and actual results was just an error code.
You are storing only the file name in the array, not its complete path or extension. You need to change this, and allow it to store FileName with extension.
string[] file = Directory.GetFiles(loc + #"\shortcuts").Select(System.IO.Path.GetFileName).ToArray();
and then, you need to change the If condition as follows.
if (file.Contains(typed))
{
File.Delete(Path.Combine(loc + #"\shortcuts",typed));
Console.WriteLine("hi");
}
In this Scenario, user would need to input the file name with extension.
If you want the User to input only the filename(without extension, as in your code), then, you could run into a situation where there could be two files with different extension.
"test.jpg"
"test.bmp"
Update
Based on your comment that you cannot store extensions, please find the updated code below. In this scenario, you do not need to change the array. Since you are only storing lnk files, you can append the extension to the file name to complete the path during Path.Combine.
if (file.Contains(typed))
{
File.Delete(Path.Combine(loc , #"shortcuts",$"{typed}.lnk"));
Console.WriteLine("hi");
}
I am using coded ui automation in Visual Studio 2012. So I have a requirement where I have to write some generic/common methods which can be used with any type of UI control.
I an new to coded ui. How to write such methods so that i can reuse it in code.
Basically, for example I want common methods for verifying certain control/Tiles/TAB/Objects is visible or not on UI.
NOTE:- I found below solution from some blog, might be this could be helpful.
To replace the UIMap, we are going to use the power of Generics in the .Net Framework. For ease of use in our testing, I built a static extension so that I could attach it to any UITestControl and use a SearchFor method to find things. As you can see in my code below, it is pretty straight forward. I use dynamics to pass in variables that I can use for both the SearchProperties and FilterProperties to go find items in the application. If you need to find more information on the controls you can use the “Coded UI Test Builder” to get more detailed information.
using Microsoft.VisualStudio.TestTools.UITesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blog.Example
{
public static class CodedUIExtension
{
public static T SearchFor<T>(this UITestControl _this, dynamic searchProperties, dynamic filterProperties = null) where T : UITestControl, new()
{
T ctrl = new T();
ctrl.Container = _this;
IEnumerable<string> propNames = ((object)searchProperties).GetPropertiesForObject();
foreach (var item in propNames)
{
ctrl.SearchProperties.Add(item, ((object)searchProperties).GetPropertyValue(item).ToString());
}
if (filterProperties != null)
{
propNames = ((object)filterProperties).GetPropertiesForObject();
foreach (var item in propNames)
{
ctrl.FilterProperties.Add(item, ((object)filterProperties).GetPropertyValue(item).ToString());
}
}
return ctrl as T;
}
private static IEnumerable<string> GetPropertiesForObject(this object _this)
{
return (from x in _this.GetType().GetProperties() select x.Name).ToList();
}
private static object GetPropertyValue(this object _this, string propName)
{
var prop = (from x in _this.GetType().GetProperties() where x.Name == propName select x).FirstOrDefault();
return prop.GetValue(_this);
}
}
}
Next, let’s see how to use this in a test. You can just start out with a basic class template using the File –> New in Visual Studio. You will see in my example below that I have added some “using” statements to bring in the testing framework while also adding some attributes for CodedUITest and TestMethod. Once you have these in place you can get started writing your test. Since we are not using the Coded UI Test Generator here, we will go ahead and add the items we need on our own. Not only are we going to remove the brittleness here but we are also going to be efficient.
The first thing I do in my test is to open a Browser and go to a url. In my case I am going to our blog. This will open up the browser and navigate all in one line (nifty). Next we are going to start to find the items we need to interact with on the screen. As you can see the first item I am going to go get n my test is the header section. This is a custom html control with the tagname “HEADER.” Once I find this control, I am going to use it in the next section so that I have a container to search within. To be honest, I really don’t have to do this, but I did want to show you that you can search for items using a container instead of having to search the entire DOM every time. Next I will get the search button control and use the “Mouse.Click” operation to click and open the search text box. Once the Coded UI Test finds the search box, it automates the text I want and use and then uses keyboard controls to send the ENTER key for the search.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.VisualStudio.TestTools.UITest.Extension;
using Microsoft.VisualStudio.TestTools.UITesting;
using Microsoft.VisualStudio.TestTools.UITesting.WinControls;
using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Keyboard = Microsoft.VisualStudio.TestTools.UITesting.Keyboard;
using Mouse = Microsoft.VisualStudio.TestTools.UITesting.Mouse;
using MouseButtons = System.Windows.Forms.MouseButtons;
namespace Blog.Example
{
[CodedUITest]
public class SimpleUITestWithoutCodedUI
{
[TestMethod]
public void SimpleWebTest()
{
//open the default browser and navigate to a web page - blog.falafel.com
BrowserWindow browser = BrowserWindow.Launch(new Uri("http://blog.falafel.com"));
//we can use controls as a way to narrow down the search for other controls
var headerSection = browser.SearchFor<HtmlCustom>(new { TagName = "HEADER" });
//let's search for something
var searchIcon = headerSection.SearchFor<HtmlHyperlink>(new { href = "http://blog.falafel.com/#searchbox" });
Mouse.Click(searchIcon);
var searchInput = browser.SearchFor<HtmlEdit>(new { name = "s" }, new { type = "INPUT" });
searchInput.Text = "treats and tricks";
Keyboard.SendKeys("{ENTER}");
//find our searched for item
var postToLookFor = browser.SearchFor<HtmlCustom>(new { TagName = "ARTICLE" }, new { InnerText = "31 Days of Visual Studio 2015 Tricks and Treats Blog Post" });
//validate our search
Assert.IsTrue(postToLookFor.Exists);
}
}
}
The next thing I do on the search result screen is find the item that I am interested in evaluating. I made that sound really easy, but having dynamic controls show up and find them is one of the hardest things to do in any Testing Framework. With the power of C# and the flexibility of the Coded UI Framework, I am able to dynamically find my items using search and filter properties so that I can evaluate them. The rest of the test, including the assertion, are basic unit testing techniques.
Like that?
public bool IsVisible(Control control)
{
return control.Visible;
}
I implemented a generic search function as such:
public static ControlType IdentifyControlByIdentifierEqualsValue<ControlType>(UITestControl parent, ControlIdentifier identifierTypeAndValue) where ControlType : UITestControl
{
var control = (ControlType)Activator.CreateInstance(typeof(ControlType), new UITestControl[] { parent });
control.SearchProperties.Add(identifierTypeAndValue.Type, identifierTypeAndValue.Value);
var wasFound = control.TryFind();
if (!wasFound)
throw new UITestControlNotFoundException("The control of type " + control.GetType().ToString() + " with the identifier type of " + identifierTypeAndValue.Type + " and the identifying attribute of " + identifierTypeAndValue.Value + " was not able to be found");
return control;
}
With the supporting class
public class ControlIdentifier
{
public ControlIdentifier(string type, string id)
{
Type = type;
Value = id;
}
public string Type { get; set; }
public string Value { get; set; }
}
Called as such:
IdentifyControlByIdentifierEqualsValue<WpfTabList>(workWindow,
new ControlIdentifer(WpfButton.PropertyNames.Name, "OK");
I would like to add a recursive command to this script that allows it to loop through a current direcotries sub directory/files and set the permissions on the subfolders/files to whatever I would like. Here is what I have so far which allows for the permissions to be changed on the first set of subdirectories. Obviously, I can add the samecode in to keep diving down through the folder structure, but not every root folder will have the same amount of sub folders within it. I want to add the recursive command to loop through all subdirectories and when there are no more, move on to the next root folder.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.AccessControl;
using System.Management;
using System.Management.Instrumentation;
namespace ApplyPermissions
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void selectDirectoryBtn_Click(object sender, EventArgs e)
{
FolderBrowserDialog myFolderBrowserDialog = new FolderBrowserDialog();
myFolderBrowserDialog.ShowDialog();
selectedDirBox.Text = myFolderBrowserDialog.SelectedPath.ToString();
try
{
DirectoryInfo myDirectoryInfo = new DirectoryInfo(selectedDirBox.Text);
foreach (DirectoryInfo currentDir in myDirectoryInfo.GetDirectories())
{
toolStripStatusLabel1.Text = currentDir.Name;
DirectorySecurity DirSecurity = currentDir.GetAccessControl();
DirSecurity.AddAccessRule(new FileSystemAccessRule(“Whatever permissions group I choose”, FileSystemRights.CreateFiles, AccessControlType.Allow));
currentDir.SetAccessControl(DirSecurity);
// Step thru each file within current Directory and assign access
foreach (FileInfo currentFile in currentDir.GetFiles())
{
FileSecurity fileSecurity = currentFile.GetAccessControl();
fileSecurity.AddAccessRule(new FileSystemAccessRule("Whatever permissions group I choose", FileSystemRights.FullControl, AccessControlType.Allow));
currentFile.SetAccessControl(fileSecurity);
}
foreach (DirectoryInfo subDir in currentDir.GetDirectories ())
{
toolStripStatusLabel1.Text = currentDir.Name + "/" + subDir.Name;
DirectorySecurity allsubDirSecurity = subDir.GetAccessControl();
allsubDirSecurity.AddAccessRule(new FileSystemAccessRule("Whatever permissions group I choose ", FileSystemRights.FullControl, AccessControlType.Allow));
subDir.SetAccessControl(allsubDirSecurity);
// Step thru each file within current SubDirectory and assign access
foreach (FileInfo currentFile in subDir.GetFiles())
{
FileSecurity fileSecurity = currentFile.GetAccessControl();
fileSecurity.AddAccessRule(new FileSystemAccessRule("Whatever permissions group I choose", FileSystemRights.FullControl, AccessControlType.Allow));
currentFile.SetAccessControl(fileSecurity);
}
}
}
labelFinished.Text = "Completed Successfully";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "/////////////////" + ex.StackTrace);
}
}
}
}
First, if your target framework is 4.0, recommend that you use the Directory.EnumerateFiles method (you can also find 3rd code that does the same thing.)
Assuming this is a no-go, you can simplify your recursive processing by using the yield keyword, e.g. make a traverse method based on yield -- I'm showing this with a filter function to since it would often be useful in directory traversal ad should give you ideas.
static IEnumerable<string> traverse(string path, Func<string, bool> filter)
{
foreach (string f in Directory.GetFiles(path).Where(filter))
{
yield return f;
}
foreach (string d in Directory.GetDirectories(path))
{
foreach (string f in traverse(d, filter))
{
yield return f;
}
}
}
Then you use traversal() this way
var files = traverse(PATH, WHERE);
foreach (string f in files) { DoWhatever; }
You will have a more easily reusable directory traversal at your fingertips. I know that I am not yielding directories in the snippet above, but if I wanted to process both files and directory, I would base this on the DirectoryInfo.GetFileSystemInfos method instead.
I forget when the yield feature was added, but it has been available for quite a while.
I've got a DBML file in my project with all my LinqToSql objects. Initially I imported them from the DB, and all was well. Now as my DB has been growing, I've been adding the new tables to the diagram in the O/R Designer, but they always get appended to the end of the XML. This is a bit of a pain, because when I'm defining foreign keys, it always lists the available tables in the order in which they appear in the XML.
Any ideas how to sort the XML table declarations alphabetically according to the table name?
I know this is old, but I also want to sort the tables and functions in my DBML to make it more manageable in Git. The following console application code seems to work pretty well. You can drag and drop a DBML file onto the exe, or you could set up a bat file or build event in your project(s).
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace DbmlSorter
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
return;
var fileName = args[0];
try
{
if (!File.Exists(fileName))
return;
SortElements(fileName);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
private static void SortElements(string fileName)
{
var root = XElement.Load(fileName);
var connections = new SortedDictionary<string, XElement>();
var tables = new SortedDictionary<string, XElement>();
var functions = new SortedDictionary<string, XElement>();
var others = new SortedDictionary<string, XElement>();
foreach (var element in root.Elements())
{
var key = element.ToString();
if (key.StartsWith("<Connection"))
connections.Add(key, element);
else if (key.StartsWith("<Table"))
tables.Add(key, element);
else if (key.StartsWith("<Function"))
functions.Add(key, element);
else
others.Add(key, element);
}
root.RemoveNodes();
foreach (var pair in connections)
{
root.Add(pair.Value);
Console.WriteLine(pair.Key);
}
foreach (var pair in tables)
{
root.Add(pair.Value);
Console.WriteLine(pair.Key);
}
foreach (var pair in functions)
{
root.Add(pair.Value);
Console.WriteLine(pair.Key);
}
foreach (var pair in others)
{
root.Add(pair.Value);
Console.WriteLine(pair.Key);
}
root.Save(fileName);
}
}
}
A possible solution is to write a small application that reads in the XML, sorts it to your liking and outputs the updated version.