// add a module tab
private void add_mod_Click(object sender, EventArgs e)
{
int TabCount = 0;
int? index = searchIndex(mod_add_textbox.Text);
if (index == null)
{
RichTextBox new_rich = new RichTextBox();
new_rich.Dock = DockStyle.Fill;
TabPage NewPage = new TabPage();
TabCount += 1;
string DocumentText = mod_add_textbox.Text;
NewPage.Name = DocumentText;
NewPage.Text = DocumentText;
NewPage.Controls.Add(new_rich);
mod_tab.TabPages.Add(NewPage);
}
else
{
mod_tab.SelectedIndex = Convert.ToInt32(index);
}
}
private async void btn_file_note_Click(object sender, EventArgs e)
{
using(OpenFileDialog ofd = new OpenFileDialog() { Filter="Text Documents|*.txt", ValidateNames = true, Multiselect = false })
{
if(ofd.ShowDialog() == DialogResult.OK)
{
using (StreamReader sr = new StreamReader(ofd.FileName))
{
mod_tab.SelectedTab.Text = await sr.ReadToEndAsync();
}
}
}
}
The problem I am getting is that when I try to open a document it is opening it into the tab name rather than the rich text box inside the tab. I have changed the "mod_tab.SelectedTab" part to the name of the rich text box within the tab however I want it so whichever tab the user has selected it opens in there. Any suggestions? thank you.
You assigned the value to the Text property of selected tab. Instead you should assign the value to Text property of RichTextBox or use Load method of RichTextBox to load content. for example:
this.richTextBox1.Text = ....
Also when you create the tab and RichTextBox dynamically like you ar doing in your code, you can find it this way:
//It means: Find all RichTextBox control which are children of mod_tab.SelectedTab
//And return first of them.
var rtb = this.mod_tab.SelectedTab.Controls.OfType<RichTextBox>().FirstOrDefault();
rtb.Text = ...
Also this way:
//It means get the first child control of mod_tab.SelectedTab
//And convert it to RichTextBox.
var rtb = this.mod_tab.SelectedTab.Controls[0] as RichTextBox;
rtb.Text = ...
Related
I'm trying to change the text of a TextBox when I click a Button: both Controls are dynamically created as run-time.
The Buttons and the TextBoxes are created every time I click on another Button.
The Name Property for each control is specified by the User, using a TextBox.
For example, the user inputs "Test1", then the Button is named btn_Test1, and the TextBox is named txt_Test1.
The Button should open a FolderBrowserDialog and after a selection has been made, the TextBox shows the path selected.
I'm using the following code:
protected void button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
folderBrowserDialog.ShowDialog();
string TextName = button.Name.Replace("btn_", "txt_");
TextBox selectText = new TextBox();
selectText = this.Controls[TextName] as TextBox;
selectText.Text = folderBrowserDialog.SelectedPath;
}
however this part gives me null:
selectText = this.Controls[TextName] as TextBox;
I did check with the debugger when I create the controls, so TextName is setting the correct Name.
The Buttons and TextBoxes are inserted in a TabControls, the Tab Name is set to the value the user inputs, so the main TabControl gets 2 controls.
I'm using a hidden TabControl named "TabFolders" that will be the main reference for creating tab clones
I'm using this code:
private void CreateDynamicPathButtons(string TabName)
{
TabPage MyNewTab = new TabPage(TabName);
TabPage TabCopy1;
tabControlEmpresas.TabPages.Add(MyNewTab);
TabControl tc = new TabControl();
tc.Location = new System.Drawing.Point(6, 6);
tc.Size = TabFolders.Size;
for (int i = 0; i < TabFolders.TabCount; i++) {
TabFolders.SelectTab(i);
TabCopy1 = new TabPage(TabFolders.SelectedTab.Text);
foreach (Control c in TabFolders.SelectedTab.Controls) {
Control cNew = (Control)Activator.CreateInstance(c.GetType());
cNew.Text = c.Text;
cNew.Size = c.Size;
cNew.Location = new System.Drawing.Point(c.Location.X, c.Location.Y);
cNew.Visible = true;
if (cNew is TextBox) {
cNew.Name = "txt_" + MyNewTab.Text + "_" + TabFolders.SelectedTab.Text;
}
if (cNew is Button) {
cNew.Name = "btn_" + MyNewTab.Text + "_" + TabFolders.SelectedTab.Text;
cNew.Click += new EventHandler(button_Click);
}
TabCopy1.Controls.Add(cNew);
}
tc.TabPages.Add(TabCopy1);
}
MyNewTab.Controls.Add(tc);
}
After many attempts I did find a very simple solution.
TextBox selectText = new TextBox();
selectText = button.Parent.Controls[TextName] as TextBox;
The button parent hast all the controls.
Assuming that button is the Button control you're creating at run-time you mentioned, you're creating a TextBox control but you're not adding it to the Form.Controls collection (this.Controls.Add([Control])).
Also, you should assign a Location, using a logic that fits your current Layout, to position the newly created Controls. Otherwise, all new controls will be positioned one on top of the other. In the example, the new Control position is determined using a field (int ControlsAdded) that keeps track of the number of Controls created at run-time and add some basic layout logic.
But, if you want to keep a reference of these new Controls, you should add them to a List<Control> or some other collection that allows to select them if/when required.
int ControlsAdded = 0;
protected void button_Click(object sender, EventArgs e)
{
TextBox selectedText = new TextBox();
selectedText.Size = new Size(300, this.Font.Height);
selectedText.Location = new Point(100, ControlsAdded * selectedText.Height + 30);
ControlsAdded += 1;
this.Controls.Add(selectedText);
selectedText.BringToFront();
using (var fBD = new FolderBrowserDialog()) {
if (fBD.ShowDialog() == DialogResult.OK)
selectedText.Text = fBD.SelectedPath;
}
}
with selectText = this.Controls[TextName] as TextBox;, you are trying to find button with replaced name which is not available in this case, and hence it returns null. This is logical mistake.
also string TextName = button.Name.Replace("btn_", "txt_"); does not replace button name, it just assigns replaced string to TextName.
The proper implementation would be
protected void button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
folderBrowserDialog.ShowDialog();
button.Name = button.Name.Replace("btn_", "txt_");
TextBox selectText = new TextBox();
selectText = this.Controls[button.Name] as TextBox;
selectText.Text = folderBrowserDialog.SelectedPath;
}
I'm creating a Word add-in which allows the user to select various text in a Word document and click a button on the ribbon which will wrap that text with a Content Control (rich text). Eventually these content controls will then be mapped to XML.
The code so far is like this:
public partial class Ribbon1
{
private RichTextContentControl titleRichTextControl;
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
}
private void addTitle_Click(object sender, RibbonControlEventArgs e)
{
AddRichTextControlAtSelection();
}
private void AddRichTextControlAtSelection()
{
word.Document currentDocument = Globals.ThisAddIn.Application.ActiveDocument;
currentDocument.ActiveWindow.Selection.Range.Select();
Document extendedDocument = Globals.Factory.GetVstoObject(currentDocument);
titleRichTextControl = extendedDocument.Controls.AddRichTextContentControl("titleRichTextControl");
titleRichTextControl.PlaceholderText = "Enter the title";
titleRichTextControl.Title = "Title";
titleRichTextControl.Tag = "title";
}
}
All this is fine and it works for the first time the button is clicked. However, if there is more than one 'title' (in this case) that needs adding, and the user presses the button a second time, it throws the error:
The control cannot be added because a control with the name titleRichTextControl already exists in the Controls collection.
It's clear why it complains, but i can't think of the correct way to go to allow multiple clicks of the button to generate multiple content controls of the same type (rich text content control) and the same name ("title" for example).
Can anybody point me in the right direction please.
OK this was how i did it in the end:
private void addTitle_Click(object sender, RibbonControlEventArgs e)
{
AddRichTextControlAtSelection();
}
int count = 0;
private void AddRichTextControlAtSelection()
{
word.Document currentDocument = Globals.ThisAddIn.Application.ActiveDocument;
Document extendedDocument = Globals.Factory.GetVstoObject(currentDocument);
if (currentDocument.ContentControls.Count > 0)
{
currentDocument.ActiveWindow.Selection.Range.HighlightColorIndex = word.WdColorIndex.wdYellow;
currentDocument.ActiveWindow.Selection.Range.Select();
richTextControls = new List<RichTextContentControl>();
foreach (word.ContentControl nativeControl in currentDocument.ContentControls)
{
if (nativeControl.Type == Microsoft.Office.Interop.Word.WdContentControlType.wdContentControlRichText)
{
count++;
RichTextContentControl tempControl = extendedDocument.Controls.AddRichTextContentControl("VSTORichTextControl" + count.ToString());
richTextControls.Add(tempControl);
tempControl.Title = "Title";
tempControl.Tag = "title";
break;
}
}
}
else
{
RichTextContentControl VSTORichTextControl;
VSTORichTextControl = extendedDocument.Controls.AddRichTextContentControl("VSTORichTextControl");
VSTORichTextControl.PlaceholderText = "Enter the DM title";
VSTORichTextControl.Title = "Title";
VSTORichTextControl.Tag = "title";
}
}
I am trying to create a program where a listbox has a number of items. Each new item has to be automatically intertwined with a checkbox and a numericUpDown. So for example Item A would have the checkbox ticked, with 50 in the numericUpDown while Item B will have the checkbox unchecked and with 25 in the numericUpDown If possible, I would like to do this via dictionary<> This is the code I have so far:
The class I have created
class MediaClass
{
public bool Checked { get; set; }
public int Number { get; set; }
}
This is my dictionary code
public void Dictionary()
{
var dictionary = new Dictionary<String, MediaClass>();
listBox_Movielist.DataSource = new BindingSource(dictionary, null);
}
I would also like this to be saved to a text file. My save code is
private void button_Save_Click(object sender, EventArgs e)
{
SaveFileDialog savefile = new SaveFileDialog();
savefile.Filter = "Text files|*.txt";
savefile.Title = "Save As";
savefile.ShowDialog();
}
My load code is
OpenFileDialog loadfile = new OpenFileDialog();
loadfile.DefaultExt = "txt";
loadfile.Filter = "Text files|*.txt";
loadfile.FilterIndex = 1;
loadfile.CheckFileExists = true;
loadfile.CheckPathExists = true;
loadfile.Multiselect = false;
loadfile.ShowDialog();
System.IO.StreamReader lText = new
System.IO.StreamReader(loadfile.FileName);
listBox_Movielist.Text = lText.ReadToEnd();
Asuming your ListBox is called listbox, add this in the constructor for your window:
listbox.SelectionChanged += (sender, e) =>
{
var item = listbox.SelectedItem as ListBoxItem;
string media = item.Content as string;
if (media != null)
{
//set checkbox to dictionary[media].Checked
//set updown to dictionary[media].Number
}
};
I'm not quite sure why you declare your dictionary in an extra method. This will make it impossible to reference outside of that method. What you probably want is to have the dictionary be a private field. Something like
private Dictionary<String, MediaClass> dictionary = new Dictionary<String, MediaClass>();
somewhere in your window class.
In pushing forward with my application (winforms) and I have found a need to have dynamically generated content to be pushed to a button that then will display that dynamic content in a messagebox.
What I am doing is reading FTP links from a file, based on a product selection, then I want to take each line and have it append a textbox and a button so that they can fill out the file name.
I have it it working where the Label, textbox and button all appear as i would expect. Now what I want is to have the button when clicked display my content that was just generated.
So the code I have right now that generates everything as expected is as follows. I just need to know how to make the button accept my ftpLabel.Text and tb.Text data. I have tried to follow the post here: How can i create dynamic button click event on dynamic button?
However, I cannot seem to make it accept any of my dynamic content.
private void productComboBox_SelectedItemChanged(object sender, EventArgs e)
{
// Read from the text file and out put the results
try
{
using (StreamReader sr = new StreamReader(selectedProduct + ".txt"))
{
string line;
int l = 0;
// build the ftp link records line by line
while ((line = sr.ReadLine()) != null)
{
Label ftpLabel = new Label();
ftpLabel.AutoSize = true;
ftpLabel.Text = line;
TextBox tb = new TextBox();
Button bt = new Button();
bt.Text = "Copy Link";
bt.Click += bt.Click;
flp.Controls.Add(ftpLabel);
flp.Controls.Add(tb);
flp.Controls.Add(bt);
l++;
}
ftpGroupBox.Controls.Add(flp);
}
}
// If the read fails then output the error message in the same section
catch (Exception ex)
{
Label ftpErrorLabel = new Label();
ftpErrorLabel.AutoSize = true;
ftpErrorLabel.ForeColor = Color.Red;
ftpErrorLabel.Text = "Error: " + ex.Message;
flp.Controls.Add(ftpErrorLabel);
ftpGroupBox.Controls.Add(flp);
}
}
void bt_Click(object sender, EventArgs e)
{
MessageBox.Show("Does this work?");
// this message displays but cannot pass my dynamicly created content to this
}
Any Advice is appreciated.
Thanks
You need a hook between the button and the corresponding label and textbox. This is probably not the correct way to do this but the easiest way it to induce a naming convention as a hook.
try
{
using (StreamReader sr = new StreamReader(selectedProduct + ".txt"))
{
string line;
int l = 0;
// build the ftp link records line by line
while ((line = sr.ReadLine()) != null)
{
Label lFTPtextext = new Label()
{
AutoSize = true,
Text = line,
Tag = l
};
Button bt = new Button()
{
Text = "Copy Link",
Tag = l
}
bt.Click += bt.Click;
TextBox tb = new TextBox()
{
Tag = l
}
flp.Controls.Add(lFTPtextext);
flp.Controls.Add(tb);
flp.Controls.Add(bt);
l++;
}
ftpGroupBox.Controls.Add(flp);
}
}
// If the read fails then output the error message in the same section
catch (Exception ex)
{
Label ftpErrorLabel = new Label();
ftpErrorLabel.AutoSize = true;
ftpErrorLabel.ForeColor = Color.Red;
ftpErrorLabel.Text = "Error: " + ex.Message;
flp.Controls.Add(ftpErrorLabel);
ftpGroupBox.Controls.Add(flp);
}
}
void bt_Click(object sender, EventArgs e)
{
string tagNumber = ((Button)sender).Tag.ToString();
var tbText= this.Controls.OfType<TextBox>()
.Where(x => x.Tag.ToString() == tagNumber)
.FirstOrDefault()
var lblText = this.Controls.OfType<Label>()
.Where(x => x.Tag.ToString() == tagNumber)
.FirstOrDefault()
MessageBox.Show(tbText.ToString() + " " + lblText.ToString());
}
Maybe not the best answer, but its how I would solve it.
Can I create a button with both .Image and .Text properties simultaniously, in such way, that text is not visible on form, and is created just for identifying what button should do at the moment?
Using TextAlign and TextImageRelation properties doesn't help. Text is always visible, just a position changes.
private System.Windows.Forms.Button bRenameCourse;
this.bRenameCourse.BackColor = System.Drawing.SystemColors.ButtonFace;
this.bRenameCourse.Image = ((System.Drawing.Image)(resources.GetObject("bRenameCourse.Image")));
this.bRenameCourse.Location = new System.Drawing.Point(966, 6);
this.bRenameCourse.Name = "bRenameCourse";
I want this text "Rename" to be not visible on button
this.bRenameCourse.Text = "Rename";
this.bRenameCourse.Size = new System.Drawing.Size(64, 60);
this.bRenameCourse.TabIndex = 10;
this.bRenameCourse.UseVisualStyleBackColor = false;
this.bRenameCourse.Click += new System.EventHandler(this.bRenameCourse_Click);
Here is why do I want it works :
private void bRenameCourse_Click(object sender, EventArgs e)
{
if (bRenameCourse.Text.Equals("Rename"))
{
//DO SMTHNG
bRenameCourse.Text = "OK";
}
else if (bRenameCourse.Text.Equals("OK"))
{
//DO SMTHNG
bRenameCourse.Text = "Rename";
}
}
I can avoid this using some flags, but I'd like to know if it's possible in general.
Don't use the .Text property of the button to store information.You can use the .Tag property
ie
this.bRenameCourse.Tag = "Rename";
And in the Event
private void bRenameCourse_Click(object sender, EventArgs e)
{
if (bRenameCourse.Tag.Equals("Rename"))
{
//DO SMTHNG
bRenameCourse.Tag = "OK";
}
else if (bRenameCourse.Tag.Equals("OK"))
{
//DO SMTHNG
bRenameCourse.Tag = "Rename";
}
}
Just set the .Text property to ""(blank or empty)