I'm trying to pass some strings(className & classID) and store them in a different variable(classNameClicked & classIDClicked) based on what hyperlink the user clicked.
Here is my code behind(C#) for creating the hyperlinks:
TextBlock txt = new TextBlock();
txt.TextWrapping = TextWrapping.Wrap;
txt.Foreground = Brushes.Black;
txt.FontFamily = new FontFamily("Times New Roman");
txt.FontSize = 25;
txt.Margin = new Thickness(5);
TextBlock ClassID = new TextBlock();
ClassID.Visibility = Visibility.Collapsed;
ClassID.Text = classID;
Run run = new Run(className);
Hyperlink link = new Hyperlink(run);
link.Click += Link_Click;
txt.Inlines.Add(ClassID);
txt.Inlines.Add(link);
myStackPanel.Children.Add(txt);
frame.Content = myStackPanel;
I was able to pass the string from the className to classNameClicked by extracting the text from the hyperlink using the code below:
private void Link_Click(object sender, RoutedEventArgs e)
{
classNameClicked = ((sender as Hyperlink).Inlines.FirstInline as Run).Text;
classIDClicked = (sender as Textblock).Text;
Class_Page class_page = new Class_Page();
NavigationService.Navigate(class_page);
}
However, I cant seem to figure out how to extract the string from classID.
Please help.
You just have to reference the parent of your Hyperlink.
So instead of
classNameClicked = ((sender as Hyperlink).Inlines.FirstInline as Run).Text;
classIDClicked = (sender as TextBlock).Text;
you can write
Hyperlink link = sender as Hyperlink;
classNameClicked = (link.Inlines.FirstInline as Run).Text;
classIDClicked = (link.Parent as TextBlock).Inlines.OfType<Run>().First().Text;
If you don't want to use LINQ you could also write:
classIDClicked = ((link.Parent as TextBlock).Inlines.FirstInline as Run).Text;
But I have the same overall opinion as Mat in the comments. This is really ugly and MVVM would be the way to go for writing much cleaner code.
Additionally you should probably add some null checking too.
Edit as requested in the comment:
If you don't want to display the classID in your GUI then you could hide it in the Tag of the Hyperlink:
Hyperlink link = new Hyperlink(run);
link.Tag = classID;
link.Click += Link_Click;
And then just get it in your Click handler:
classIDClicked = link.Tag as string;
You don't need a hidden TextBlock for that.
Related
My WinForms program uses a WebBrowser control, and it creates a new TabPage with a WebBrowser control inside whenever the NewWindow event is triggered, using the following code:
private void WebBrowser1_NewWindow(object sender, System.ComponentModel.CancelEventArgs e)
{//open new window in new browser tab
string newUrl = browser.Document.ActiveElement.GetAttribute("href");
string pageName = "Page " + (tabControl1.TabCount + 1).ToString();
TabPage detailsTab = new TabPage(pageName);
Button closeTab = new Button();
closeTab.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
closeTab.Location = new Point(10, 10);
closeTab.Text = "Close Tab";
closeTab.Click += new EventHandler(btnCloseTab_Click);
tabControl1.TabPages.Add(detailsTab);
WebBrowser detailsBrowser = new WebBrowser();
detailsBrowser.Dock = DockStyle.Fill;
detailsBrowser.Navigate(newUrl);
detailsTab.Controls.Add(detailsBrowser);
detailsTab.Controls.Add(closeTab);
closeTab.BringToFront();
tabControl1.SelectedIndex = tabControl1.TabCount -1;
}
So that each time a new browser tab is opened, a WebBrowser control called detailsBrowser is added to that tab. The problem is, if I need to get an HTML element from that browser, using something like:
HtmlElement saveButton = detailsBrowser.Document.GetElementsByTagName("input").GetElementsByName("save")[0];
I have no idea which detailsBrowser will be used to pull that HtmlElement.
I tried using
tabControl1.SelectedTab.Controls["detailsBrowser"]
instead of just referencing the browser by name, but this doesn't work and returns null when I try to get an HtmlElement from the browser.
Does anyone have a recommendation for how to specify a control using its container when multiple controls have the same name? Or is there a way to give each programmatically generated WebBrowser control a unique name?
Thanks!
EDIT: Here's the method I'm trying to use with the WebBrowser to select HTML elements:
public void addNote(string noteText)
{
WebBrowser currentBrowser = (WebBrowser) tabControl1.SelectedTab.Controls["detailsBrowser"];
HtmlElement showNotesButton = null;
//var links = browser.Document.GetElementsByTagName("div");
var links = currentBrowser.Document.GetElementsByTagName("div");
foreach (HtmlElement link in links)
{
if (link.GetAttribute("className") == "user_info_link")
{
showNotesButton = link;
}
}
//HtmlElement noteBox = browser.Document.GetElementById("remark");
HtmlElement noteBox = currentBrowser.Document.GetElementById("remark");
//HtmlElement submitNote = browser.Document.GetElementById("save_note");
HtmlElement submitNote = currentBrowser.Document.GetElementById("save_note");
showNotesButton.InvokeMember("click");
noteBox.Focus();
noteBox.InnerText = noteText;
Thread.Sleep(50);
submitNote.InvokeMember("click");
}
I'm trying to get the values that a user inputs in a textbox in a dynamically generated form. Another method loads and parses an XML file and creates an object that has specific getters and setters for the settings that it finds in the file (Server, Port, Title, etc.).
The dynamic form is created using labels and textboxes like this. It was designed only to display the information from the XML file, and I am trying to implement a system that allows users to edit the information before saving it again to the file. I'm doing alright with the methods to save and edit the XML file, but I'm lost for how to associate the input in any given textbox with the associated label representing the key in the XML file to change.
Below is the current form implementation where the labels and textboxes are created as part of a foreach loop. I tried creating textbox.Leave eventHandler to track when the user has finished changing a value, but I can't figure out how to know what label it is associated with.
var sortedSettings = new SortedDictionary<string, string>(theSettings.Settings);
int numSettings = sortedSettings.Count;
TextBox[] txt = new TextBox[numSettings];
Label[] label = new Label[numSettings];
int labelSpacing = this.labelSecond.Top - this.labelTop.Bottom;
int textSpacing = this.textBoxSecond.Top - this.textBoxTop.Bottom;
int line = 0;
foreach (KeyValuePair<string, string> key in sortedSettings)
{
label[line] = new Label();
label[line].Text = key.Key;
label[line].Left = this.labelTop.Left;
label[line].Height = this.labelTop.Height;
label[line].Width = this.labelTop.Width;
txt[line] = new TextBox();
txt[line].Text = key.Value;
txt[line].Left = this.textBoxTop.Left;
txt[line].Height = this.textBoxTop.Height;
txt[line].Width = this.textBoxTop.Width;
txt[line].ReadOnly = false;
// Attach and initialize EventHandler for template textbox on Leave
txt[line].Leave += new System.EventHandler(txt_Leave);
if (line > 0)
{
label[line].Top = label[line - 1].Bottom + labelSpacing;
txt[line].Top = txt[line - 1].Bottom + textSpacing;
}
else
{
label[line].Top = this.labelTop.Top;
txt[line].Top = this.textBoxTop.Top;
}
this.Controls.Add(label[line]);
this.Controls.Add(txt[line]);
line++;
}
private void txt_Leave(object sender, EventArgs e)
{
String enteredVal = sender;
FormUtilities.FindAndCenterMsgBox(this.Bounds, true, "EventChecker");
MessageBox.Show("The current value of LABEL is " + enteredVal, "EventChecker");
}
One option is to use TextBox.Tag property.
Example (in foreach loop):
txt[line] = new TextBox();
txt[line].Text = key.Value;
txt[line].Tag = label[line];
To get label associated with TextBox:
TextBox t = txt[0];
Label l = t.Tag as Label;
//Here is how you identify textbox which generated the event.
private void txt_Leave(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
//..
}
I have a radio buttons and one text box on a panel made dynamically . Now, I want to disable the text box when the second radio button is checked, means they are both connected. how can I make the event for it. I want to have the event working.
Thanks a lot in advanced.
this is my code which is not working:
Panel pnl = new Panel();
pnl.Name = "pnl_";
pnl.Size = new Size(630, 80);
RadioButton rd = new RadioButton();
rd.Name = "rd_" + dr[i]["Value_Name"].ToString();
rd.Text = dr[i]["Value_Name"].ToString();
rd.Location = new Point(i,i*2);
pnl.Controls.Add(rd);
TextBox txt = new TextBox();
txt.Name = "txt_" + Field_Name+"_"+dr[i]["Value_Name"].ToString();
txt.Size = new Size(171, 20);
txt.Text = Field_Name + "_" + dr[i]["Value_Name"].ToString();
txt.Location = new Point(20, 30);
pnl.Controls.Add(txt);
////// ???? ////////
rd.CheckedChanged += new EventHandler(eventTxt(txt));
void eventTxt(object sender,EventArgs e,TextBox txt)
{
RadioButton rd = (RadioButton)sender;
txt.Enabled = rd.Checked;
}
Use a lambda to close over the relevant variable(s):
rd.CheckedChanged += (s, args) => txt.Enabled = rd.Checked;
If you had more than a one line implementation, you could call out to a method accepting whatever parameters you've closed over, instead of including it all inline.
I would suggest to set the Tag of the radio button and get walk down the dependencies.
rd.Tag = txt;
In the event handler use this:
TextBox txt = (sender as Control).Tag as TextBox;
txt.Enabled = ...
you can use code given
rd.CheckedChanged += (s,argx) => txt.Enabled = rd.Checked;
Here's how you could create an event for it:
//if you are using Microsoft Visual Studio, the following
//line of code will go in a separate file called 'Form1.Design.cs'
//instead of just 'Form1.cs'
myTextBox.CheckChangedEventHandeler += new EventHandeler(checkBox1_CheckChanged); //set an event handeler
public void checkBox1_CheckChanged(object sender, EventArgs e) //what you want to happen every time the check is changed
{
if(checkBox1.checked == true) //replace 'checkBox1' with your check-box's name
{
myTextBox.enabled = false; //replace 'myTextbox' with your text box's name;
//change your text box's enabled property to false
}
}
Hope it helps!
I want to make a button that can drop down a multi-line label or form which contains help documentation for the user.
I have searched and I can't find anything that is for C# Winforms. Do any free controls out there exist for this or will I have to create it myself?
Many thanks,
Richard
Using ToolStripControlHost and ToolStripDropDown controls can provide this for you:
private void button1_Click(object sender, EventArgs e) {
var helpInfo = new StringBuilder();
helpInfo.AppendLine("This is line one.");
helpInfo.AppendLine("This is line two.");
var textHelp = new TextBox() { Multiline = true,
ReadOnly = true,
Text = helpInfo.ToString(),
MinimumSize = new Size(100, 100)
};
var toolHost = new ToolStripControlHost(textHelp);
toolHost.Margin = new Padding(0);
var toolDrop = new ToolStripDropDown();
toolDrop.Padding = new Padding(0);
toolDrop.Items.Add(toolHost);
toolDrop.Show(button1, button1.Width, 0);
}
Result:
I think it will be a bad user experience to see a tooltip on click of a button. However, you can use this if you really want to
var b = new Button();
b.Click += (sender, args) => new ToolTip().Show("Help documentation", b.Parent, new Point(b.Location.X, b.Location.X + 10));
I want to create ajax dragpanel dynamically and add the controls and panel dynamically.I used the below code for create the control dynamically.But I can`t able to drag it.
enter code here
protected void Page_PreInit(object sender, EventArgs e)
{
DragPanelExtender drg = new DragPanelExtender();
drg.ID = "drg_1";
drg.DragHandleID = "pnl_1";
drg.TargetControlID = "pnl_2";
Panel p1 = new Panel();
p1.ID = "pnl_1";
Panel p2 = new Panel();
p2.ID = "pnl_2";
Label l1 = new Label();
l1.Text = "First";
TextBox t = new TextBox();
t.Text = "Enter text";
p2.Controls.Add(l1);
p2.Controls.Add(t);
p1.Controls.Add(p2);
Page.Controls.Add(p1);
}
How to I create drag controls inside the panel