try
{
Form frmShow = new Form();
TextBox txtShowAll = new TextBox();
frmShow.StartPosition = FormStartPosition.CenterScreen;
frmShow.Font = this.Font;
frmShow.Size = this.Size;
frmShow.Icon = this.Icon;
frmShow.Text = "All data";
txtShowAll.Dock = DockStyle.Fill;
txtShowAll.Multiline = true;
frmShow.Controls.Add(txtShowAll);
frmShow.ShowDialog();
StreamReader r = new StreamReader("empData.txt");
string strShowAllData = r.ReadToEnd();
txtShowAll.Text = strShowAllData;
r.Close();
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
I sure that is the file name is correct
when I run the program it shows an empty text box.
The result
I just noticed you are adding text to the textbox after showing the form in dialog mode. Why don't you move the frmShow.ShowDialog(); to the end of the try block just like I have done it in the code below, and make sure the empData.txt exists at its path.
try
{
Form frmShow = new Form();
TextBox txtShowAll = new TextBox();
frmShow.StartPosition = FormStartPosition.CenterScreen;
frmShow.Font = this.Font;
frmShow.Size = this.Size;
frmShow.Icon = this.Icon;
frmShow.Text = "All data";
txtShowAll.Dock = DockStyle.Fill;
txtShowAll.Multiline = true;
frmShow.Controls.Add(txtShowAll);
StreamReader r = new StreamReader("empData.txt");
string strShowAllData = r.ReadToEnd();
txtShowAll.Text = strShowAllData;
r.Close();
frmShow.ShowDialog();
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
As noted other places, the actual problem stems from the show dialog blocking before you can execute your dialog
There are a couple of things here
Why don't you create a dedicated Form i.e MyDeciatedShowAllForm, instead of dynamically creating it
If you are using something that implements IDisposable, Its best to use a using statement
Example
using(var r = new StreamReader("empData.txt"))
{
string strShowAllData = r.ReadToEnd();
txtShowAll.Text = strShowAllData;
}
Why don't you use File.ReadAllText instead, save your self some printable characters
Example
string strShowAllData = File.ReadAllText(path);
You probably need to set the TextBox to MultiLine
Example
// Set the Multiline property to true.
textBox1.Multiline = true;
// Add vertical scroll bars to the TextBox control.
textBox1.ScrollBars = ScrollBars.Vertical;
// Allow the RETURN key to be entered in the TextBox control.
textBox1.AcceptsReturn = true;
// Allow the TAB key to be entered in the TextBox control.
textBox1.AcceptsTab = true;
// Set WordWrap to true to allow text to wrap to the next line.
textBox1.WordWrap = true;
// Show all data
textBox1.Text = strShowAllData;
Why don't you check if the file exists first using File.Exists
Exmaple
if(!File.Exists("someFile.txt"))
{
MessageBox.Show(!"oh nos!!!!! the file doesn't exist");
return;
}
Lastly, and this is one you need to remember, you need to learn how to use the debugger and breakpoints, Navigating through Code with the Debugger. I mean, you should have known if there is text or not in your text file if you had just put a breakpoint on txtShowAll.Text = strShowAllData; there should be no doubt in your mind or ours.
Related
Hello im having trouble with file dialog
Standard code, but it's freezing while selecting large files (600MB+ xls file that i need to first reformat to xlsb, then stream data from, but that is not important here).
What i wanted to achieve is to hide dialog when Open button is clicked, so that i could display Loading Message.
Yet im not sure how can i achieve that. Can i somehow subscribe to Open button?
OpenFileDialog openFile = new OpenFileDialog() { DereferenceLinks = false };
openFile.Title = "Select Supplier List";
openFile.Filter = "Excel files (*.*xls*)|*.*xls*";
try
{
if (openFile.ShowDialog() == true)
{
/* Takes long time to go after selection */
ViewModel.ReportPath = openFile.FileName;
ViewModel.FileTrueName = Path.GetFileName(ViewModel.ReportPath);
}
}
catch
{
ViewModel.ReportPath = null;
ViewModel.FileTrueName = null;
}
Wrapping code with task, helped :)
Some changes happened during searching for answer, based on comments.
Task.Run(() =>
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Title = "Select Supplier List";
openFile.Filter = "Excel Files(*.xls; *.xlsx; *.xlsb; *.xlsm)| *.xls; *.xlsx; *.xlsb; *.xlsm";
try
{
if (openFile.ShowDialog() == true)
{
ViewModel.ReportPath = openFile.FileName;
ViewModel.FileTrueName = Path.GetFileName(ViewModel.ReportPath);
}
}
catch
{
ViewModel.ReportPath = null;
ViewModel.FileTrueName = null;
}
});
I'm trying to make a "Choose your own adventure game" in C#, and having a problem with the buttons. I have 6 buttons, and I want to reuse them for the different options on each "page" of the story. Program Window
As an example, I was using this for btn1.
void page1(){
txtStory.Text = "Can you sneak past the enemy?";
btn1.Click += (sender, args) => {
luckCheck();
if (lucky) {page2(); clearButtons();}
else {page3(); clearButtons();}
};
}
void luckCheck(){
int luckTest = gen.Next(1,12);
if (luckTest <= playerLuck) {lucky = true;}
else {lucky = false;}
}
void clearButtons(){
btnN.Text = "";
btnS.Text = "";
btnE.Text = "";
btnW.Text = "";
btn1.Text = "";
btn2.Text = "";
btn3.Text = "";
btn4.Text = "";
btn5.Text = "";
btn6.Text = "";
}
void page2(){
txtStory.Text = "Lucky!";
}
void page3(){
txtStory.Text = "Not Lucky!";
}
Even though it has moved on to another method, if clicked, btn1 still repeats the same command from page1. Is there a way to stop this from happening? Like clearing the memory for the button or something.
The problem you're having is that page1() is attaching an anonymous handler method, which is never detached, so each time you call it, you are just adding more and more handlers.
But this design is going to get out of hand very quickly once you start adding lots of pages.
Consider a different design, where you have a Page class to represent each page. That class would have the story as a property on it, and a collection of possible Choices (rather than hard-coding 6 of them). Choice is a class with a Description string property and an Action method to be executed if it is used.
Your application can hold the CurrentPage property, and your Choice's Action will need to be able to navigate by changing that page. Etc, etc...
Hope this helps.
P.S. extra tip. Rather than returning the result of the luckCheck method on a class field, consider redesigning it to return the result:
bool luckCheck(){
int luckTest = gen.Next(1,12);
return luckTest <= playerLuck;
}
Without going into details as to how the code above could be structured better, here is a solution using C# 7. Note how a local function is assigned to handle the event then unassigned - using Delegate Type Inference
void page1(){
txtStory.Text = "Can you sneak past the enemy?";
void Btn1Click(object s, EventArgs ev)
{
luckCheck();
if (lucky) {page2(); clearButtons(); btn1.Click -= Btn1Click; }
else {page3(); clearButtons();}
};
btn1.Click += Btn1Click;
void luckCheck(){
int luckTest = gen.Next(1,12);
if (luckTest <= playerLuck) {lucky = true;}
else {lucky = false;}
}
void clearButtons(){
btnN.Text = "";
btnS.Text = "";
btnE.Text = "";
btnW.Text = "";
btn1.Text = "";
btn2.Text = "";
btn3.Text = "";
btn4.Text = "";
btn5.Text = "";
btn6.Text = "";
}
void page2(){
txtStory.Text = "Lucky!";
}
void page3(){
txtStory.Text = "Not Lucky!";
}
I have a RichTextBox and a Button that saves its text to a .txt file.
However it does not save the LineBreaks \n. It ends up all in one line.
What could be preventing it? I'm using Encoding.Unicode.
XAML
<RichTextBox x:Name="rtbMessage" Margin="10,10,10,50" />
<Button x:Name="btnSave" Content="Save" Margin="231,264,211,29" Width="75" Click="btnSave_Click"/>
C#
String message = "Hello, world.\n\n This is a test.";
Paragraph p = new Paragraph();
// Startup
// Write Message to RichTextBox
//
public MainWindow()
{
InitializeComponent();
rtbMessage.Document = new FlowDocument(p);
rtbMessage.BeginChange();
p.Inlines.Add(new Run(message));
rtbMessage.EndChange();
}
// Copy RichTextBox to String
//
public String MessageRichTextBox()
{
FlowDocument fd = new FlowDocument(p);
rtbMessage.Document = fd;
TextRange textRange = new TextRange(
rtbMessage.Document.ContentStart,
rtbMessage.Document.ContentEnd
);
return textRange.Text;
}
// Save Message to .txt File
//
private void buttonSave_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.SaveFileDialog saveFile = new Microsoft.Win32.SaveFileDialog();
// Save File Default Path same as Input Directory
saveFile.RestoreDirectory = true;
saveFile.Filter = "Text file (*.txt)|*.txt";
saveFile.DefaultExt = ".txt";
saveFile.FileName = "Message";
// Show Save File dialog box
Nullable<bool> result = saveFile.ShowDialog();
// Process dialog box
if (result == true)
{
// Save document
File.WriteAllText(saveFile.FileName, MessageRichTextBox(), Encoding.Unicode);
}
}
Looks like you are resetting the message when you grab it
public String MessageRichTextBox()
{
FlowDocument fd = new FlowDocument(p);
rtbMessage.Document = fd;
Seems unnecessary and might the cause. I cant validate without a windows machine next to me (sorry on a Mac right now), just give it a try though
I use richtextbox, but I use Environment.NewLine instead of "\n".
In your example:
String message = "Hello, world." + Environment.NewLine + Environment.NewLine + "This is a test.";
Maybe that is a workaround.
Change
TextRange textRange = new TextRange(
rtbMessage.Document.ContentStart,
rtbMessage.Document.ContentEnd);
To
TextRange textRange = new TextRange(
p.ContentStart,
p.ContentEnd)
I keep getting an ObjectDisposedExpection when I need to get a Form to show.
Do you guys maybe know how to do this? In the foreach by NotitiesForm.Show() I get the error ObjectDisposedExpection. I am programming in Visual Studio Ultimate 2012 C#.
RichTextBox NotitiesTB = new RichTextBox();
private Form NotitiesForm;
/// <summary>
///
/// </summary>
/// <param name="label"></param>
///
public void NotitiesLatenZien()
{
if (filename != null)
{
BRTSignal signal = new BRTSignal(filename);
BRTEventRepository Notities = new BRTEventRepository(signal);
List<IBRTNote> note = Notities.ReadNotes();
BRTEventService TijdNotities = new BRTEventService(signal);
TijdNotities.MakeNoteTimesRelativeToTrack(note, 1);
//TextBox NotitiesTB = new TextBox();
//NotitiesTB.Name = "Notities";
if (NotitiesForm == null)
{
NotitiesForm = new Form();
}
NotitiesForm.Height = 600;
NotitiesForm.Width = 1000;
NotitiesForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
NotitiesForm.MaximizeBox = false;
NotitiesForm.Disposed +=NotitiesForm_Disposed;
NotitiesForm.Text = "Notities";
NotitiesTB.Multiline = true;
NotitiesTB.Height = 600;
NotitiesTB.Width = 980;
NotitiesTB.ReadOnly = true;
NotitiesTB.Clear();
//NotitiesTB.Click += NotitiesTB_Click;
//NotitiesTB.SelectionStart = Convert.ToInt32(referenceLineSelectedPage);
NotitiesTB.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Both;
NotitiesTB.Name = "Notities";
NotitiesForm.Controls.Add(NotitiesTB);
foreach (IBRTNote notes in Notities.ReadNotes())
{
//string test = Convert.ToString((notes.Time));
//textBox1.Text = String.Concat(textBox1.Text, string.Concat(Environment.NewLine, notes.Text));
if (NotitiesTB.Text == "")
{
NotitiesTB.Text += new BRTToDotNET.RTDateTime((long)notes.Time).ToDotNet().ToString() + " " + notes.Text;
}
else
{
NotitiesTB.Text += "\r\n" + new BRTToDotNET.RTDateTime((long)notes.Time).ToDotNet().ToString() + " " + notes.Text;
}
//MessageBox.Show("\r\n" + notes.Text);
NotitiesForm.Show();
NotitiesForm.BringToFront();
}
}
else
{
MessageBox.Show("Er blijkt een .sig file te missen. Controleer of u een .sig file heeft ingeladen.");
}
}
private void NotitiesForm_Disposed(object sender, EventArgs e)
{
NotitiesForm = null;
}
The code you posted seem "good enough". That is, you set the NotitiesForm variable when the object is disposed, and you create a new one if it's null. As long as all this code executes in the main UI thread, that part is fine.
But note that all controls in a Form are disposed of when the Form is disposed. So your NotitiesTB control will be disposed of the first time your NotitiesForm is closed. You then add that control to the next Form instance you create, and when it's shown, you get the exception because you're trying to show a Form containing a control that has already been disposed.
The right way to do this would be to design an actual Form subclass that already contains the RichTextBox instance you want. Then you don't have to keep adding a new instance to each new instance of the Form you create.
Barring that, then you need to create a new RichTextBox instance to go with each new Form instance you create, e.g. in the same place where you have the NotitiesForm = new Form(); statement.
I've installed com0com so that I can write a NUnit test. Just in case there is a definition difference of Keyboard wedge a brief description of it is a piece of software that listens to a Serial communications device, reads any data sent to it (in my case formats it to ASCII data) then sends that to a Virtual keyboard. This code does work in production but we are required to now either document our code or have a unit test to prove how it is supposed to be used. so here is my test
[Test()]
public void WedgeSendsTextToVirtualKeyboardTest()
{
(var form = new Form())
using(var sp = new System.IO.Ports.SerialPort("COM"+COMB, 115200))
using (var wedge = new KeyboardWedgeConfiguration(WEDGE_KEY))
{
sp.Open();
TextBox tb = SetupForm(form);
TurnOnKeyboardWedge(wedge);
form.Activate();
form.Activated += (s, e) =>
{
tb.Focus();
};
while (!tb.Focused) { }
string str = "Hello World";
sp.Write(str);
//wait 1 second. This allows data to send, and pool in the wedge
//the minimum wait time is 200ms. the string then gets put into bytes
//and shipped off to a virtual keyboard where all the keys are pressed.
System.Threading.Thread.Sleep(1000);
Expect(tb.Text, Is.EqualTo(str));
}
}
private static TextBox SetupForm(Form form)
{
TextBox tb = new TextBox();
tb.Name = "tb";
tb.TabIndex = 0;
tb.AcceptsReturn = true;
tb.AcceptsTab = true;
tb.Dock = DockStyle.Fill;
form.Controls.Add(tb);
form.Show();
return tb;
}
private static void TurnOnKeyboardWedge(KeyboardWedgeConfiguration wedge)
{
wedge.Port = COMA;
wedge.PortForwardingEnabled = true;
wedge.Baud = 115200;
System.IO.Ports.SerialPort serialPort;
wedge.StartRerouting();
Assert.IsTrue(wedge.IsAlive(out serialPort));
Assert.IsNotNull(serialPort);
}
When the test runs, the form shows, no text is put in the textbox, then the test exits and the last assert fails (Expect(tb.Text, Is.EqualTo(str));) saying that tb.Text is string.Empty. I've tried a number of different tactics to get focus on that textbox (i'm assuming that is the problem atleast). At one time I made my sleep longer so that I had time to click on the textbox and type myself, and I couldn't click on the box (I'm assuming that is because of the sleep operation... which is also probably why my wedge can't type in there as well) so how can I fix this problem and make my test pass. Again this code does work in a production environment, so I am 100% convinced it is my test (and probably that sleep operation)
I was able to make my test pass with the help of this question stackoverflow question (thank you so much Patrick Quirk). It is actually a minor variation to it. I'm not even sure if my solution is 100% correct, but when the form pops up the text is entered and my test passes. The solution was two part system. First I had to make a class that extends Form override the Text property, and listen for the Activated and FormClosing Events. On Form Closing I would set my text, and on Activated I told my TextBox to have the focus.
private class WedgeForm : Form
{
public override string Text { get { return text; } set { text = value; } }
string text = string.Empty;
private TextBox tb;
public WedgeForm()
{
InitializeControls();
Activated += (s, e) => { tb.Focus(); };
FormClosing += (s, e) => { this.Text = tb.Text; };
}
private void InitializeControls()
{
tb = new TextBox();
tb.Name = "tb";
tb.TabIndex = 0;
tb.AcceptsReturn = true;
tb.AcceptsTab = true;
tb.Multiline = true;
tb.Dock = DockStyle.Fill;
this.Controls.Add(tb);
}
}
then using the InvokeEx method that was provided in the other qustion/answer My test easy to setup
[Test()]
public void WedgeSendsTextToVirtualKeyboardTest()
{
using (var form = new WedgeForm())
using (var wedge = new KeyboardWedgeConfiguration(WEDGE_KEY))
{
TurnOnKeyboardWedge(wedge);
string actual = MakeWedgeWriteHelloWorld(form, wedge); ;
string expected = "Hello World";
Expect(actual, Is.EqualTo(expected));
}
}
private static string MakeWedgeWriteHelloWorld(WedgeForm form, KeyboardWedgeConfiguration wedge)
{
var uiThread = new Thread(() => Application.Run(form));
uiThread.SetApartmentState(ApartmentState.STA);
uiThread.Start();
string actual = string.Empty;
var thread = new Thread
(
() => actual = InvokeEx<Form, string>(form, f => f.Text)
);
using (var sp = new System.IO.Ports.SerialPort("COM" + COMB, 115200))
{
sp.Open();
sp.Write("Hello World");
}
//wait 1 second. This allows data to send, and pool in the wedge
//the minimum wait time is 200ms. the string then gets put into bytes
//and shipped off to a virtual keyboard where all the keys are pressed.
Thread.Sleep(1000);
InvokeEx<Form>(form, f => f.Close());
thread.Start();
uiThread.Join();
thread.Join();
return actual;
}
One minor thing I have to remember when running this test is to not be clicking around because if that textbox loses focus I'm sunk. But the test is only 1second long.. I think I'll live.