private void tbLog_TextChanged(object sender, TextChangedEventArgs e)
{
//Get only NEW text added to Log
}
/*
LOG
old message...
old message...
old message...
old message...
NEW message...
NEW message...
NEW message...
NEW message...
NEW message...
*/
How to I get only NEW text from the TextBox?
Perhaps you should be using the TextChangedEventArgs.Changes property:
var fullText = tbLog.Text;
if (e.Changes.Any())
{
var additions = e.Changes.Where(tc => tc.AddedLength > 0);
var newTexts = additions.Select(tc => fullText.Substring(tc.Offset, tc.AddedLength));
// TODO: Do stuff with the new pieces of text
}
Something like this?
private string old_text = "";
private void tbLog_TextChanged(object sender, TextChangedEventArgs e)
{
if(old_text != tbLog.Text)
{
writeLog(tbLog.Text);
old_text = tbLog.Text;
}
}
For desktop WPF text boxes, you should be able to use TextChangedEventArgs.Changes to enumerate the changes. Note a single event may contain several changes.
The TextChange class has Offset, AddedLength, and RemovedLength properties that give you the exact range of characters that were changed.
private void textTx1Asc_TextChanged(object sender, EventArgs e)
{
string s;
//get only the new chars
s = textTx1Asc.Text;
s = s.Remove(0, prev_len);
//update prev_len for next time
prev_len = textTx1Asc.TextLength;
//s contains only the new characters, process here
}
Related
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 still confused whats better to use, datagridview or Be.HexEditor,
I am pretty sure I'll be able to do it with datagridview, but I like be.hex more, especially speed, UI etc...
But I tried to understand the code of be.hex, and I can't figure out how does it work, and also is it possible to show values from bytes arrays to the HexBox(not only from opening .bin files). it also uses dynamicFileByteProvider, and there is no info on the net about this class.
dynamicFileByteProvider = new DynamicFileByteProvider(fileName);
dynamicFileByteProvider.Changed += new EventHandler(byteProvider_Changed);
dynamicFileByteProvider.LengthChanged += new EventHandler(byteProvider_LengthChanged);
my app will open 1024 bytes files max, and also it will read bytes from comm port
I've tinkered a bit with this. What I did was
1) put an invisible picture box as control placeholder on the form, here named ph1
2) configure the HexBox control in Form_Load()
private HexBox hexBox;
private void Form1_Load(object sender, EventArgs e)
{
hexBox = new HexBox()
{
Top = ph1.Top,
Width = ph1.Width,
Height = ph1.Height,
Left = ph1.Left,
Visible = true,
UseFixedBytesPerLine = true,
BytesPerLine = 16,
ColumnInfoVisible = true,
LineInfoVisible = true,
StringViewVisible = true,
VScrollBarVisible = true
};
this.Controls.Add(hexBox);
this.Controls.Remove(ph1);
}
3) Load the actual file in DragDrop event
var filePath = ((string[])(e.Data.GetData(DataFormats.FileDrop)))[0];
var source = new FileByteProvider(filePath);
hexBox.ByteProvider = source;
hexBox.Refresh();
Example after drag/drop of a docx file onto the form:
Edit: if you wish to provide some self-generated array of bytes, it is as simple as this:
byte[] byteArr = {0xaa, 0x3f, 0x4b};
hexBox.ByteProvider = new DynamicByteProvider(byteArr);
Edit 2: To save the contents of the hex box:
I am sure there is some better way to do this. What I found for now is to simply add a handler in the hex box definition block:
hexBox.CopiedHex += HexBox_CopiedHex;
Have some kind of "save" button with such a code:
private void button1_Click(object sender, EventArgs e)
{
hexBox.SelectAll();
hexBox.CopyHex();
hexBox.SelectionLength = 0;
}
And such an event handler:
private void HexBox_CopiedHex(object sender, EventArgs e)
{
var hex = Clipboard.GetText();
var hexHex = hex.Split(' ');
var hexArr = new byte[hexHex.Length];
for (var i = 0; i < hexHex.Length; i++)
{
hexArr[i] = byte.Parse(hexHex[i], NumberStyles.AllowHexSpecifier);
}
File.WriteAllBytes(#"C:\00_Work\test.bin", hexArr);
}
To show byte[] in hexbox use new DynamicByteProvider(byte[]
To get modified byte[] from hexbox
use DynamicByteProvider.Bytes.ToArray()
I can't figure out how the whole thing is built. Do i need to add each link by my self manually ? And if i have 100 links ?
This is a screenshot of what i see in the xmal file
But maybe i can add this links from the code it self ?
The code is long so i will not add it to here.
I got the project from here:
Background File Downloader
If i want to add to the downloader my own links ?
I see in the DownloaderDemo code this part that add the links:
// Get the contents of the rich text box
string rtbContents = new TextRange(rtbPaths.Document.ContentStart, rtbPaths.Document.ContentEnd).Text;
foreach (string line in rtbContents.Split('\n'))
{
String trimmedLine = line.Trim(' ', '\r');
if (trimmedLine.Length > 0)
{
// If the line is not empty, assume it's a valid url and add it to the files list
// Note: You could check if the url is valid before adding it, and probably should do this is a real application
downloader.Files.Add(new FileDownloader.FileInfo(trimmedLine));
}
}
But i don't understand what richTextBox ? I guess it's in the design in the DownloaderDemo.xaml
Still if i want to add my own links to download files ?
This is DownloaderDemo.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace FileDownloaderApp
{
/// <summary>Interaction logic for DownloaderDemo.xaml</summary>
public partial class DownloaderDemo : Window
{
// Creating a new instance of a FileDownloader
private FileDownloader downloader = new FileDownloader();
public DownloaderDemo()
{
InitializeComponent();
CommandBindings.Add(new CommandBinding(ApplicationCommands.Close,
new ExecutedRoutedEventHandler(delegate(object sender, ExecutedRoutedEventArgs args) { this.Close(); })));
downloader.StateChanged += new EventHandler(downloader_StateChanged);
downloader.CalculatingFileSize += new FileDownloader.CalculatingFileSizeEventHandler(downloader_CalculationFileSize);
downloader.ProgressChanged += new EventHandler(downloader_ProgressChanged);
downloader.FileDownloadAttempting += new EventHandler(downloader_FileDownloadAttempting);
downloader.FileDownloadStarted += new EventHandler(downloader_FileDownloadStarted);
downloader.Completed += new EventHandler(downloader_Completed);
downloader.CancelRequested += new EventHandler(downloader_CancelRequested);
downloader.DeletingFilesAfterCancel += new EventHandler(downloader_DeletingFilesAfterCancel);
downloader.Canceled += new EventHandler(downloader_Canceled);
}
public void DragWindow(object sender, MouseButtonEventArgs args)
{
DragMove();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.Height -= 30;
}
// A simple implementation of setting the directory path, adding files from a textbox and starting the download
private void btnStart_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.FolderBrowserDialog openFolderDialog = new System.Windows.Forms.FolderBrowserDialog();
if (openFolderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
// Set the path to the local directory where the files will be downloaded to
downloader.LocalDirectory = openFolderDialog.SelectedPath;
// Clear the current list of files (in case it's not the first download)
downloader.Files.Clear();
// Get the contents of the rich text box
string rtbContents = new TextRange(rtbPaths.Document.ContentStart, rtbPaths.Document.ContentEnd).Text;
foreach (string line in rtbContents.Split('\n'))
{
String trimmedLine = line.Trim(' ', '\r');
if (trimmedLine.Length > 0)
{
// If the line is not empty, assume it's a valid url and add it to the files list
// Note: You could check if the url is valid before adding it, and probably should do this is a real application
downloader.Files.Add(new FileDownloader.FileInfo(trimmedLine));
}
}
// Start the downloader
downloader.Start();
}
}
private void btnPause_Click(object sender, RoutedEventArgs e)
{
// Pause the downloader
downloader.Pause();
}
private void btnResume_Click(object sender, RoutedEventArgs e)
{
// Resume the downloader
downloader.Resume();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
// Stop the downloader
// Note: This will not be instantantanious - the current requests need to be closed down, and the downloaded files need to be deleted
downloader.Stop();
}
// This event is fired every time the paused or busy state is changed, and used here to set the controls of the interface
// This makes it enuivalent to a void handling both downloader.IsBusyChanged and downloader.IsPausedChanged
private void downloader_StateChanged(object sender, EventArgs e)
{
// Setting the buttons
btnStart.IsEnabled = downloader.CanStart;
btnStop.IsEnabled = downloader.CanStop;
btnPause.IsEnabled = downloader.CanPause;
btnResume.IsEnabled = downloader.CanResume;
// Enabling or disabling the setting controls
rtbPaths.IsReadOnly = downloader.IsBusy;
cbUseProgress.IsEnabled = !downloader.IsBusy;
}
// Show the progress of file size calculation
// Note that these events will only occur when the total file size is calculated in advance, in other words when the SupportsProgress is set to true
private void downloader_CalculationFileSize(object sender, Int32 fileNr)
{
lblStatus.Content = String.Format("Calculating file sizes - file {0} of {1}", fileNr, downloader.Files.Count);
}
// Occurs every time of block of data has been downloaded, and can be used to display the progress with
// Note that you can also create a timer, and display the progress every certain interval
// Also note that the progress properties return a size in bytes, which is not really user friendly to display
// The FileDownloader class provides static functions to format these byte amounts to a more readible format, either in binary or decimal notation
private void downloader_ProgressChanged(object sender, EventArgs e)
{
pBarFileProgress.Value = downloader.CurrentFilePercentage();
lblFileProgress.Content = String.Format("Downloaded {0} of {1} ({2}%)", FileDownloader.FormatSizeBinary(downloader.CurrentFileProgress), FileDownloader.FormatSizeBinary(downloader.CurrentFileSize), downloader.CurrentFilePercentage()) + String.Format(" - {0}/s", FileDownloader.FormatSizeBinary(downloader.DownloadSpeed));
if (downloader.SupportsProgress)
{
pBarTotalProgress.Value = downloader.TotalPercentage();
lblTotalProgress.Content = String.Format("Downloaded {0} of {1} ({2}%)", FileDownloader.FormatSizeBinary(downloader.TotalProgress), FileDownloader.FormatSizeBinary(downloader.TotalSize), downloader.TotalPercentage());
}
}
// This will be shown when the request for the file is made, before the download starts (or fails)
private void downloader_FileDownloadAttempting(object sender, EventArgs e)
{
lblStatus.Content = String.Format("Preparing {0}", downloader.CurrentFile.Path);
}
// Display of the file info after the download started
private void downloader_FileDownloadStarted(object sender, EventArgs e)
{
lblStatus.Content = String.Format("Downloading {0}", downloader.CurrentFile.Path);
lblFileSize.Content = String.Format("File size: {0}", FileDownloader.FormatSizeBinary(downloader.CurrentFileSize));
lblSavingTo.Content = String.Format("Saving to {0}\\{1}", downloader.LocalDirectory, downloader.CurrentFile.Name);
}
// Display of a completion message, showing the amount of files that has been downloaded.
// Note, this does not hold into account any possible failed file downloads
private void downloader_Completed(object sender, EventArgs e)
{
lblStatus.Content = String.Format("Download complete, downloaded {0} files.", downloader.Files.Count);
}
// Show a message that the downloads are being canceled - all files downloaded will be deleted and the current ones will be aborted
private void downloader_CancelRequested(object sender, EventArgs e)
{
lblStatus.Content = "Canceling downloads...";
}
// Show a message that the downloads are being canceled - all files downloaded will be deleted and the current ones will be aborted
private void downloader_DeletingFilesAfterCancel(object sender, EventArgs e)
{
lblStatus.Content = "Canceling downloads - deleting files...";
}
// Show a message saying the downloads have been canceled
private void downloader_Canceled(object sender, EventArgs e)
{
lblStatus.Content = "Download(s) canceled";
pBarFileProgress.Value = 0;
pBarTotalProgress.Value = 0;
lblFileProgress.Content = "-";
lblTotalProgress.Content = "-";
lblFileSize.Content = "-";
lblSavingTo.Content = "-";
}
// Setting the SupportsProgress property - if set to false, no total progress data will be avaible!
private void cbUseProgress_Checked(object sender, RoutedEventArgs e)
{
downloader.SupportsProgress = (Boolean)cbUseProgress.IsChecked;
}
// Setting the DeleteCompletedFilesAfterCancel property - indicates if the completed files should be deleted after cancellation
private void cbDeleteCompletedFiles_Checked(object sender, RoutedEventArgs e)
{
downloader.DeleteCompletedFilesAfterCancel = (Boolean)cbDeleteCompletedFiles.IsChecked;
}
// Close the window when the close button is hit
private void btnClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
You can easily add to the rich text box new download links by creating your own function that takes a new download link path, to append to the text box you do:
richTextBox.AppendText("new string of download link");
You're not sure what rich text box? It is in your .xaml file, it is called rtbPaths. So you could create a new button that executes a dialog box, takes a string and use that string to append to this text box.
It's hard to understand what is being asked here as well, sorry if I got this wrong.
I am trying to build a scratch-like application to simulate block-based programming approach. I want the user to add the commands to command pool(queue) and run them in order when the user clicks on the "RUN" button.
I researched on the internet and found queueing is possible by Action lists.
ScreenShot of the form
//Global Variables
List<Int32> NumberOfSteps = new List<Int32>();
List<Int32> NumberOfDegrees = new List<Int32>();
List<Int32> GlideXPos = new List<Int32>();
List<Int32> GlideYPos = new List<Int32>();
List<String> SayList = new List<String>();
List<String> SoundList = new List<String>();
List<Action> queue = new List<Action>();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void textBox7_TextChanged(object sender, EventArgs e)
{
}
private static Bitmap RotateImageByAngle(Image oldBitmap, float angle)
{
var newBitmap = new Bitmap(oldBitmap.Width, oldBitmap.Height);
var graphics = Graphics.FromImage(newBitmap);
graphics.TranslateTransform((float)oldBitmap.Width / 2, (float)oldBitmap.Height / 2);
graphics.RotateTransform(angle);
graphics.TranslateTransform(-(float)oldBitmap.Width / 2, -(float)oldBitmap.Height / 2);
graphics.DrawImage(oldBitmap, new Point(0, 0));
return newBitmap;
}
private void button3_Click(object sender, EventArgs e)
{
pictureBox1.Image = RotateImageByAngle(pictureBox1.Image, 30);
}
private void button1_Click(object sender, EventArgs e)
{
queue.Add(() => { HAREKETETTIR(Convert.ToInt32(txtNumberOfSteps.Text)); });
}
private void HAREKETETTIR(int miktar)
{
deneme2 += miktar;
Point deneme = new Point(deneme2, 455);
pictureBox1.Location = deneme;
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void btnRotate_Click(object sender, EventArgs e)
{
queue.Add(() => { HAREKETETTIR(Convert.ToInt32(txtNumberOfSteps.Text)); });
}
private void RUN_Click(object sender, EventArgs e)
{
foreach (Action item in queue)
{
item();
}
}
}
When I click Run,The code creates an error as "Input string was not in a correct format."
How can I solve the issue here?
Thanks
Your question does not contain information, which part of program produces error, but it is probably Convert.ToInt32(txtNumberOfSteps.Text).
First reason of error could be that txtNumberOfSteps.Text does not contain text convertible to integer, so make sure user can enter only valid integer or provide appropriate error handling (e.g. check txtNumberOfSteps.Text before you enqueue action and display user some error message).
Second reason is more tricky to spot. If you add Action to queue like this
queue.Add(() => { HAREKETETTIR(Convert.ToInt32(txtNumberOfSteps.Text)); });
then method Convert.ToInt32() would try to convert value of txtNumberOfSteps.Text as it is in the moment you run the action, not as it was when you queued the action. So for example if user queues one action when txtNumberOfSteps.Text contains "2" and then he changes txtNumberOfSteps.Text to empty string and run actions in queue, you would received error, because empty string is not valid integer. This can be easily fixed by creating temporary variable containing copy of value in txtNumberOfSteps.Text in the moment of enqueing the action.
private void button1_Click(object sender, EventArgs e)
{
var text = txtNumberOfSteps.Text;
queue.Add(() => { HAREKETETTIR(Convert.ToInt32(text)); });
}
(and the same problem is in btnRotate_Click() method).
You can read about this problem in more detail here.
It looks to me like your error is because txtNumberOfSteps.Text is actually an invalid number. You are adding the actions to your queue correctly, and running them correctly as far as I can see.
I'm trying to implement an application in C# which generates me a QR Code. I've managed to do this, but I don't know how to call CreateQRImage(string inputData) inside the genButton_Click(object sender, EventArgs e).
I inside the windows form I have a textbox and a button, and I think that the function CreateQRImage must be called with the name of the textbox
Here is the code:
private void genButton_Click(object sender, EventArgs e)
{
}
public void CreateQRImage(string inputData)
{
if (inputData.Trim() == String.Empty)
{
System.Windows.Forms.MessageBox.Show("Data must not be empty.");
}
BarcodeWriter qrcoder = new ZXing.BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new ZXing.QrCode.QrCodeEncodingOptions
{
ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H,
Height = 250,
Width = 250
}
};
string tempFileName = System.IO.Path.GetTempPath() + inputData + ".png";
Image image;
String data = inputData;
var result = qrcoder.Write(inputData);
image = new Bitmap(result);
image.Save(tempFileName);
System.Diagnostics.Process.Start(tempFileName);
}
This should do the trick:
private void genButton_Click(object sender, EventArgs e)
{
// Assuming your text box name. Also assuming UI disables button until text is entered.
this.CreateQRImage(myTextBox.Text);
}