I'm trying to save and load the contents of a ListView list using C# .Net. I was hoping to save it by creating a variable System.Windows.Forms.ListView and then populating it with that.
Code snippet for Saving:
Properties.Settings.Default.followedUsersSettings = followerList;
Properties.Settings.Default.Save();
Code snippet for Loading:
if (Properties.Settings.Default.followedUsersSettings != null) {
followerList = Properties.Settings.Default.followedUsersSettings;
}
I can't seem to get it to work using that code. Are there any better ways of saving this that is as simple as possible? The list is single column, so an Array should also work, but i'm not sure what is recommended.
ok, I managed to get it working.
Saving:
//Convert the listview to a normal list of strings
var followerList = new List<string>();
//add each listview item to a normal list
foreach (ListViewItem Item in followerListView.Items) {
followerList.Add(Item.Text.ToString());
}
//create string collection from list of strings
StringCollection collection = new StringCollection();
//set the collection setting (created in Settings.settings as a specialized collection)
Properties.Settings.Default.followedUsersSettingsCollection = collection;
//persist the settings
Properties.Settings.Default.Save();
And for Loading:
//check for null (first run)
if (Properties.Settings.Default.followedUsersSettings != null) {
//create a new collection again
StringCollection collection = new StringCollection();
//set the collection from the settings variable
collection = Properties.Settings.Default.followedUsersSettingsCollection;
//convert the collection back to a list
List<string> followedList = collection.Cast<string>().ToList();
//populate the listview again from the new list
foreach (var item in followedList) {
followerListView.Items.Add(item);
}
}
Hopefully that makes sense to someone who found this from a Google search.
if (Properties.Settings.Default.followedUsersSettingsListView == null)
{
// adding default items to settings
Properties.Settings.Default.followedUsersSettingsListView = new System.Collections.Specialized.StringCollection();
Properties.Settings.Default.followedUsersSettingsListView.AddRange(new string [] {"Item1", "Item2"});
Properties.Settings.Default.Save();
}
// load items from settings
followerList.Items.AddRange((from i in Properties.Settings.Default.followedUsersSettingsListView.Cast<string>()
select new ListViewItem(i)).ToArray());
Related
im new at programming and need help here... I want to create a Binding with a Combobox Item.
But the DataBinding is not adding a new DataBind, it overwrites the old one because of the loop. So i want if you select a "Profilname" in the Combobox that the "Path" will be displayed.
But so far, just the last loaded .txt file will be displayed because of the overwrite.
Here is now my question: How to avoid the overwrite of the DataBind in the (foreach)-loop?
For information: There is a folder which contains many .txt-files, which are all called: "profile.txt". The Programm search for all the files with a loop and then search in the files with another loop a line, which contains the word "profile_name". And then the Name has to be displayed in the ComboBox and the Path has to be binded to the "Item"/"Text" in the ComboBox.
I hope this is understandable and sorry if my code is confusing or not very strong written, im learning...
foreach (string profiletxt in Directory.EnumerateFiles(profiledirectory, "profile.txt", SearchOption.AllDirectories))
{
foreach (string line in System.IO.File.ReadAllLines(profiletxt))
{
if (line.Contains("profile_name"))
{
string remLine = line.Remove(0, 15);
string dLine = remLine.Replace("\"", "");
// dataBinding
var listProfiles = new List<Profile>() {
new Profile() {Path = profiletxt, Name = dLine,},
};
materialComboBox1.DataSource = listProfiles;
materialComboBox1.DisplayMember = "Name";
materialComboBox1.ValueMember = "Path";
}
}
if (materialComboBox1.SelectedIndex == -1)
{
MessageBox.Show("Error, couldn't find Profiles");
}
}
public class Profile
{
public string Path { get; set; }
public string Name { get; set; }
}
a ComboBox uses its ItemSource containing the available items. In your inner foreach loop you declare a new profile list for every find of profile item:
var listProfiles = new List<Profile>() {
new Profile() {Path = profiletxt, Name = dLine,},
};
materialComboBox1.DataSource = listProfiles;
Instead, you'd probably like to create a new Profile list before the first foreach loop
var listProfiles = new List<Profile>();
and in the inner loop, add your new finding to the list
listProfiles.Add(new Profile() {Path = profiletxt, Name = dLine});
Then, after the outer loop, you may assign the new ItemSource only once.
There are other newby design flaws in your code:
there should be no need to set DisplayMember and ValueMember in the .xaml.cs "code behind". Rather it belongs into the xaml code itself as these are static.
As a more general advise, consider not doing any kind of "business rules stuff" or data holding in your code behind. Rather you like to separate your UI ("View") from your data ("Model") while a "ViewModel" separates these two and implements the business rules. There are tons of good introductions on this MVVM programming pattern out there.
Plain and simply, I have a c:\dropdowntest.docx file that has nothing but one single dropdown list. The dropdown list has two options, "Option1" and "Option2". The file is saved so that "Option1" is selected. How do I select the "Option2" by using the Open XML SDK in C#?
Here's a start for the code, so I'm for example able to refer to the dropdown list:
private static void LoopElements(WordprocessingDocument wordDocument)
{
List<SdtElement> sdtelements = wordDocument.MainDocumentPart.Document.Descendants<SdtElement>().ToList();
foreach (var contentcontrol in sdtelements)
{
var listitems = contentcontrol.Descendants<ListItem>().ToList();
if (listitems.Count > 0)
{
SdtRun xStdRun = (SdtRun)contentcontrol;
Here is how you can replace the previously selected option with the last one from listitems:
private static void LoopElements(WordprocessingDocument wordDocument)
{
List<SdtElement> sdtelements = wordDocument.MainDocumentPart.Document.Descendants<SdtElement>().ToList();
foreach (var contentcontrol in sdtelements)
{
var listitems = contentcontrol.Descendants<ListItem>().ToList();
if (listitems.Count > 0)
{
SdtRun xStdRun = (SdtRun)contentcontrol;
SdtContentRun xStdContentRun = xStdRun.SdtContentRun;
Text xStdContentText = xStdContentRun.GetFirstChild<Run>().GetFirstChild<Text>();
xStdContentText.Text = listitems.Last().DisplayText;
}
}
}
Also just in case, you should probably check these answers as well, they address things like what if you don't have a selected option (there is no Run element in SdtContentRun), or what if you have SdtBlock instead of SdtRun, etc.
I'm trying to pull out the list of files and directories listed in an open Explorer window (in the same order as they're displayed) so that I can look through it, then set focus to a particular item.
I found this code here that allows me to get the selected items, however I'm not sure if it's possible to use this approach to get all items:
List<string> SelectedFiles() {
string filename;
List<string> selected = new List<string>();
var shell = new Shell32.Shell();
foreach (SHDocVw.InternetExplorer window in new SHDocVw.ShellWindows()) {
filename = Path.GetFileNameWithoutExtension(window.FullName).ToLower();
if (filename.ToLowerInvariant() == "explorer") {
((Shell32.IShellFolderViewDual2)window.Document).SelectItem()
foreach (Shell32.FolderItem item in items) {
selected.Add(item.Path);
}
}
}
return selected;
}
It looks like this Shell32 approach would also allow me to select an item programmatically, which is the other part I'm trying to accomplish. Instead of SelectedItems(), I would call SelectItem(), though I'm not sure how to use that function.
Anyone know of a way to get the list of files/directories from an open Windows Explorer window (and ideally set focus to an item)? Perhaps a P/Invoke kind of thing?
I was able to modify that code snippet I found to list all files/directories instead of just the selected ones.
Here's what I ended up with:
List<string> FilesAndFolders() {
string filename;
List<string> explorerItems = new List<string>();
var shell = new Shell32.Shell();
foreach (SHDocVw.InternetExplorer window in new SHDocVw.ShellWindows()) {
filename = Path.GetFileNameWithoutExtension(window.FullName).ToLower();
if (filename.ToLowerInvariant() == "explorer") {
Shell32.Folder folder = ((Shell32.IShellFolderViewDual2)window.Document).Folder;
Shell32.FolderItems items = folder.Items();
foreach (Shell32.FolderItem item in items) {
explorerItems.Add(item.Path);
}
}
}
return explorerItems;
}
Edit:
To select an item, you call:
((Shell32.IShellFolderViewDual2)window.Document).SelectItem(item, 1);
where window is a SHDocVw.InternetExplorer, and item is a Shell32.FolderItem (from folder.Items() in the above example).
To deselect, it, pass in 0 instead of 1 as the second overload.
I actually display on my Listbox this list of item that i retrive from XML . When I click on an Item i am going back to the same method and creating a new list to display with different items.
I am wondering why it's not clearing the previous list.
This is the code I use, I can't figure this out ..
if (e.Error == null)
{
// Retrieving the subfolders
XDocument xdoc = XDocument.Parse(e.Result, LoadOptions.None);
XNamespace aNamespace = XNamespace.Get("http://schemas.datacontract.org/2004/07/System.IO");
var folders = from query in xdoc.Descendants(aNamespace.GetName("DirectoryInfo"))
select new Folder
{
Name = (string)query.Element("OriginalPath"),
};
ObservableCollection<Folder> LFolders = new ObservableCollection<Folder>();
foreach (Folder f in folders)
{
LFolders.Add(f);
}
listBox1.ItemsSource = LFolders;
listBox1.SelectionChanged += new SelectionChangedEventHandler(listBox1_SelectionChanged);
}
Two suggestions:
Consider using the MVVM pattern and then storing and updating your ObservableCollection on the view model instead.
Set the SelectionChanged event in XAML instead of where you're setting it now. For every call to this method you're appending an additional event handler to your listBox1.
If you set the Itemssource to null before you set the new value, I believe that will work. Also, you can try making LFolders a class variable. When you begin the method, clear the collection and then add to it. THe observable collection that is bound to the listbox will take care of updating the listbox.
I am using a Transitionals Slideshow control which has an observable collection of strings bound to the itemsource. These strings are the file paths to each picture in the slidehow. When I first load the WPF app, it runs this method correctly (using a directory path to generate the PicSlideShowCollection):
public void SelectImages(string path)
{
// Validate
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
PicSlideShowCollection.Clear();
// Get directory info for specified path
DirectoryInfo di = new DirectoryInfo(path);
// Image mask
string[] extensions = new string[] { "*.jpg", "*.png", "*.gif", "*.bmp" };
// Search for all
foreach (string extension in extensions)
{
foreach (FileInfo fi in di.GetFiles(extension.ToLower()))
{
PicSlideShowCollection.Add(fi.FullName);
}
}
}
However, I have a button that allows the user to change the directory of images to use in the slideshow and re-runs the above method. When that is executed, I get this error:
GeneratorPosition '-1,1' passed to Remove does not have Offset equal
to 0.
This occurs on the PicSlideShowCollection.Clear() instruction.
If I comment that instruction, the new directory images get ADDED TO the original directory pictures which is NOT what I want.
I know this has to do with the PicSlideShowCollection being used as an item source to the Slide show control, but I need to know how I can prevent this error from occuring.
Thank you!
Slideshow.AutoAdvance = false;
Slideshow.SelcetedIndex=-1;
var count=PicSlideShowCollection.Count;
forearch(var item in newsources)
{
PicSlideShowCollection.Add(item);
}
while(count--)
PicSlideShowCollection.RemoveAt(0);
Slideshow.SelcetedIndex=0;
I can't explain why this error occurs. GeneratorPosition is used by the ItemContainerGenerator of an ItemsControl, which should simply work when you bind to its ItemsSource property and add or remove items to/from the source collection. Clearing the source collection is of course also a valid operation.
A possible workaround for the problem would be to reset the ItemsSource each time you switch to another image directory. So instead of clearing the existing collection
PicSlideShowCollection.Clear();
create a new collection and set ItemsSource to the new collection:
PicSlideShowCollection = new ObservableCollection<string>();
slideShowControl.ItemsSource = PicSlideShowCollection;