I am wondering why my selection index changed is firing twice when I click on an item on my list.
This is the code I use in the selectionindexchanged
private void listBoxFolders_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Taking the name of the folder to pass in the parameters
if ((Folder)listBoxFolders.SelectedItem != null)
{
folderTmp = (Folder)listBoxFolders.SelectedItem;
}
// Connection to the webservice to get the subfolders and also the files
WebClient wc = new WebClient();
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted2);
wc.DownloadStringAsync(new Uri("http://clients.uicentric.net/IISHostedCalcService/FilesService.svc/GetFoldersAndFiles?selectedFolder=" + folderTmp.Name));
}
and this is the method which is firing twice inside it:
public void wc_DownloadStringCompleted2(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
XDocument xdoc = XDocument.Parse(e.Result, LoadOptions.None);
XNamespace aNamespace = XNamespace.Get("http://schemas.datacontract.org/2004/07/System.IO");
try
{
// Retrieving the subfolders
var folders = from query in xdoc.Descendants(aNamespace.GetName("DirectoryInfo"))
select new Folder
{
Name = (string)query.Element("OriginalPath"),
};
_lFolders = new ObservableCollection<Folder>();
foreach (Folder f in folders)
{
LFolders.Add(f);
}
listBoxFolders.ItemsSource = LFolders;
listBoxFolders.DisplayMemberPath = "Name";
// Retrieving the files
var files = from query in xdoc.Descendants(aNamespace.GetName("FileInfo"))
select new File
{
Name = (string)query.Element("OriginalPath"),
};
_lFiles = new ObservableCollection<File>();
foreach (File f in files)
{
LFiles.Add(f);
}
listBoxFiles.ItemsSource = LFiles;
listBoxFiles.DisplayMemberPath = "Name";
listBoxFiles.SelectionChanged += new SelectionChangedEventHandler(listBoxFiles_SelectionChanged);
}
catch { }
}
}
You are reloading the item source of listbox upon the selection changed event. Becoause of the reload action, the index gets changed to its default value, ie, -1 .
This probably must be your issue.
Instead of using selection changed event go for Tap event.
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 implemented drag and drop and all works fine except that i can drag from the grid and drop in the same grid which duplicates files. I have tried to look at types of controls or data source but can't seem to figure it out. I tried File.Exists(file) in an if statement but didn't work
What I have tried
_attachmentGrid.DragEnter += (s, e) =>
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
else
{
e.Effect = DragDropEffects.None;
}
};
_attachmentGrid.DragDrop += (s, e) =>
{
//var newPath = Directory.GetCurrentDirectory();
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
if (files != null)
{
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
AttachFile(file);
}
}
};
_attachmentGrid.MouseDown += (s, e) =>
{
byte[] data = GetData(_selection.SingleSelection);
string fileName = _selection.SingleSelection.Entity.FileAttachment.AttachmentName;
var list = new StringCollection();
list = _manager.DragAttachment(data, fileName);
DataObject dataObject = new DataObject();
dataObject.SetFileDropList(list);
_attachmentGrid.DoDragDrop(dataObject, DragDropEffects.Move | DragDropEffects.Copy);
};```
Thank you
Ended up putting a tag in the mousedown event and checking if the tag is true in the drag drop event then not attach the files which solved my issue.
I am trying to come up with a solution where I can search items inside a combo box that contain certain word/phrase. I tried using the AutoComplete text box functionality, but that only searches for the first word which is no good to me.
I have followed the example provided at https://social.msdn.microsoft.com/Forums/vstudio/en-US/4c229a73-cdad-4fa3-95db-97f9ff7810c1/autocomplete-match-on-contains-not-startswith?forum=netfxbcl
I have initiated 2 lists
public List<string> listOnit = new List<string>();
public List<string> listNew = new List<string>();
I then load the data into a comboBox
if (rdr.HasRows == true)
{
// var source = new List<string>();
while (rdr.Read())
{
// myCollectionSales.Add(rdr[0].ToString());
listOnit.Add(rdr[0].ToString());
}
rdr.Close();
//textBox1.AutoCompleteCustomSource = myCollectionSales;
comboBox1.Items.AddRange(listOnit.ToArray());
}
and have a TextUpdate event handler to filter the list when text has changed
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
comboBox1.Items.Clear();
listNew.Clear();
foreach (var item in listOnit)
{
if (item.Contains(this.comboBox1.Text))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
}
I am coming across a problem where the search results don't return what I expect. For example, I search for the string "Bud" and I only get the following results
http://prntscr.com/ppkatd
While in the database, there is also Budweiser 33cl and Keg Budweiser (http://prntscr.com/ppkbu4), for example, which is fetched on the first list.
Should I be using a different method, rather than "Contains"?
Perhaps you are using different cases?
Try with .ToLower():
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
comboBox1.Items.Clear();
listNew.Clear();
foreach (var item in listOnit)
{
if (item.ToLower().Contains(this.comboBox1.Text.ToLower()))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
}
I am making a Windows Forms App that manages a hotel. It has Client, Room, Occupancy classes. Client and Rooms have an ArrayList that is populated at runtime from a .txt file that is then displayed in a clientListView and a roomDataGridView.
As such, I have this line of code to populate the roomsDGV:
roomsDGV.DataSource = roomsArrayList;
With the roomsDGV, I'm trying to add new Rows by clicking on the roomsDGV, like when it is NOT databound. I am also trying to edit the rows and save it to txt file after editing or as I'm editing. I can post more code as necessary but I'm not sure if showing more code will help at the current moment. In the end, I'm trying for a functionality so that I can highlight a client in the list and click on one of the rows in roomsDGV and assign that clientID to that room or any sort of way like that.
On load, the datagridview is loaded and formatted correctly from the arrayList but I seem to be having this problem of being able to edit the datagridview. It gives me this error when I click on one of the rows:
System.IndexOutOfRangeException: 'Index -1 does not have a value.'
This stems from Application.Run(new HotelManager());
Here is the form:
public partial class HotelManager : Form
{
// VARIABLES
string clientID;
// FILEPATHS
string clientsTxt = "Clients.txt";
string occupanciesTxt = "Occupancies.txt";
string roomsTxt = "Rooms.txt";
string clientsDat = "Clients.dat";
// ARRAYLIST FOR ROOMS and CLIENTS
ArrayList roomsArrayList = new ArrayList();
ArrayList clientsArrayList = new ArrayList();
//STACKS AND QUEUES INIT
// Load occupancies into stack > pop
Stack roomStack = new Stack();
Queue vacancyQueue = new Queue();
// RANDOM for ID
private readonly Random rand = new Random();
public HotelManager()
{
InitializeComponent();
}
private void HotelManager_Load(object sender, EventArgs e)
{
roomsDGV.DataSource = roomsArrayList;
// LOAD clients
// LoadClients();
RefreshClientList();
// LOAD rooms
LoadRooms();
}
private void NewClientButton_Click(object sender, EventArgs e)
{
AddClient();
}
private void checkInButton_Click(object sender, EventArgs e)
{
string clientID = clientList.SelectedItems[0].Text;
string[] text = File.ReadAllLines(occupanciesTxt);
foreach (string s in text)
{
if (s.Contains(clientID))
{
var replace = s;
Console.WriteLine(s);
replace = replace.Replace("false", "true");
}
}
File.WriteAllLines(occupanciesTxt, text);
}
// METHODS
private void AddClient()
{
//COLLECT DATA > CREATE NEW client > SHOW IN **PROGRAM/DataGridView** > add to clients file
// ID GENERATION > CHECKS AGAINST clientsTXT
clientID = rand.Next(0, 999999).ToString();
if (File.ReadLines(clientsTxt).Contains(clientID))
{
clientID = rand.Next(0, 999999).ToString();
}
Client client = new Client(clientID, firstNameBox.Text, lastNameBox.Text);
try
{
if (!string.IsNullOrWhiteSpace(phoneNumBox.Text))
{
client.PhoneNumber = Convert.ToInt64(phoneNumBox.Text);
}
if (!string.IsNullOrWhiteSpace(addressBox.Text))
{
client.Address = addressBox.Text;
}
}
catch (Exception)
{
MessageBox.Show("Please use the correct format!");
throw;
}
clientsArrayList.Add(client);
using (StreamWriter file =
new StreamWriter("Clients.txt", true))
{
file.WriteLine(client.ToString());
}
RefreshClientList();
// TEST CODE // SERIALIZATION TO .DAT
SerializeClientData(client);
}
private void LoadClients()
{
// LOADS arrayList FROM .txt FILE
List<string> clientList = File.ReadAllLines(clientsTxt).ToList();
foreach (var c in clientList)
{
Client client = new Client(c);
clientsArrayList.Add(client);
}
}
private void LoadRooms()
{
List<string> roomsList = File.ReadAllLines(roomsTxt).ToList();
foreach (var r in roomsList)
{
var roomDetails = r.Split('|');
if (r.Contains("BASIC"))
{
BasicRoom basic = new BasicRoom();
basic.RoomNumber = roomDetails[0];
basic.NumberOfBeds = Convert.ToInt32(roomDetails[1]);
basic.Balcony = Convert.ToBoolean(roomDetails[2]);
basic.DownForRepair = Convert.ToBoolean(roomDetails[3]);
basic.Smoking = Convert.ToBoolean(roomDetails[4]);
roomsArrayList.Add(basic);
}
else if (r.Contains("SUITE"))
{
Suite suite = new Suite();
suite.RoomNumber = roomDetails[0];
suite.NumberOfBeds = Convert.ToInt32(roomDetails[1]);
suite.Balcony = Convert.ToBoolean(roomDetails[2]);
suite.DownForRepair = Convert.ToBoolean(roomDetails[3]);
suite.NumberOfRooms = Convert.ToInt32(roomDetails[4]);
roomsArrayList.Add(suite);
}
}
roomStack = new Stack(roomsArrayList);
foreach (var item in roomStack)
{
Console.WriteLine(item);
}
}
private void RoomsDGV_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void RoomsDGV_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
}
}
So far I've looked through all the properties but I can't seem to find the right one. I know I can add/use comboboxes and etc to add a new item into the arrayList instead but I'm trying for datagridview functionality
I expect to edit and add rows to the DGV, but something in the designer is preventing me?
Here is the DGV, and clicking on any of the rows breaks it.
https://imgur.com/a/GG7ZwdV
check this
Insert, Update, Delete with DataGridView Control in C# (Windows Application) | A Rahim Khan's Blog
Insert, Update and Delete Records in a C# DataGridView
Good Luck
I'm really new to coding
I have a treeview that refreshes with a timer.
How can i make sure i keep my selected node highlighted every time it refreshes
Appreciate any help
Thanks
Here is the code that I have:
private void PopulateTree(ListObjectsResponse buckets)
{
treeView1.Nodes.Clear();
List<TreeItem> items = new List<TreeItem>();
foreach (S3Object obj in buckets.S3Objects)
{
treeView1.Nodes.Add(new TreeNode(obj.Key));
}
}
private void button4_Click_1(object sender, EventArgs e)
{
timer1.Enabled = true;
existingBucketName = label3.Text + "-DP";
AmazonS3Client client = new AmazonS3Client();
ListObjectsRequest listRequest = new ListObjectsRequest
{
BucketName = existingBucketName,
};
try
{
ListObjectsResponse listResponse;
listResponse = client.ListObjects(listRequest);
PopulateTree(listResponse);
}
catch
{
timer1.Enabled = false;
MessageBox.Show("There is no folder for this user");
}
}
Assuming that o.Key is a string, and that each string is unique and occurs at most once in buckets.S3Objects, try saving the selected value before repopulating the TreeView, then select it again afterwards.
private void PopulateTree(ListObjectsResponse buckets)
{
// Since you're about to clear out all current TreeNode instances, storing a
// reference to SelectedNode is not enough. You're setting o.Key as the Text
// for each TreeNode, so save the selected node's Text value.
var selectedText
= treeView1.SelectedNode == null ? "" : treeView1.SelectedNode.Text;
// Repopulate your TreeView with new TreeNodes
treeView1.Nodes.Clear();
treeView1.Nodes.AddRange(buckets.S3Objects.Select(o => new TreeNode(o.Key)).ToArray())
// Look for the TreeNode with the same Text that you had selected before.
// If it's not found, then SelectedNode will be set to null
treeView1.SelectedNode =
= treeView1.Nodes.Cast<TreeNode>()
.SingleOrDefault(n => n.Text == selectedText);
}
Several of the above methods, such as Select, Cast, and SingleOrDefault, are part of LINQ.
Assuming this is ASP.NET (not ASP.NET MVC) that you're talking about, you would do this in the Page_Load() event handler. Be sure to check whether IsPostBack == true
For example,
private void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// set selected node here
}
}
If you are using ASP.NET MVC then just store the property in the ViewBag.