WPF RichTextBox get selected element - c#

I am adding hyperlink to a RichTextEditor (link). But now I want to get the Hyperlink back when user selects the hyperlink. And here I meant I want the Hyperlink element not just the text.
What I'm trying to do is to create a pop-up like google docs for hyperlink. I can add the hyperlink just fine. But now I need to modify the existing link. Getting the display text is easy but to get the address of the link is tricky. And I don't want the whole paragraph and then look for the link because there can be multiple links in one paragraph.
I tried richtextbox.Selection.Start.GetAdjacentElement(Forward/Backward) but it's not always returning the hyperlink. Is there any way to get just the selected element/hyperlink?

Maybe, some helps are here ^^
http://blogs.msdn.com/b/prajakta/archive/2006/10/17/autp-detecting-hyperlinks-in-richtextbox-part-i.aspx
Based on reference, I try to find NavigateUri
public static Hyperlink GetHyberLink(this TextPointer pointer)
{
if (pointer == null)
{
return null;
}
Inline parent = pointer.Parent as Inline;
while (parent != null && !(parent is Hyperlink))
{
parent = parent.Parent as Inline;
}
return parent == null ? null : (Hyperlink)parent;
}
Using:
Hyperlink hyperlink = RichTextBox.Selection.Start.GetHyberLink();
TextRange textRange = new TextRange(hyperlink.ElementStart, hyperlink.ElementEnd);
textRange.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
Result:
The NavigateUri will be marked as red.

So this is what I end up doing to get the hyperlink.
Hyperlink GetHyperlinkAtSelection()
{
var selectedPointer = rtb.Selection.GetNextInsertionPosition(forward)
if(sp == null)
return;
var para = sp.Paragraph;
var hyperlink = para.Inlines.FirstOrDefault(x =>
x.ContentStart.CompareTo(sp) == -1 && x.ContentEnd.CompareTo(sp) == 1);
return hyperlink as Hyperlink;
}
to get hyperlink at caret position just change the first line of the method.

Related

How to get Selected Text from WebBrowser WPF Control and bind it to a string object?

Here is my web browser:
<WebBrowser viewmodel:BrowserBehavior.Html="{Binding SelectedNode.ContentData.FileName, Converter={StaticResource converter}, Mode=OneWay}" />
In fact, text in my WebBrowser Control can be Selected.
I wonder if I can retrieve the Selected portion in a string object?
PS: When right-clicking the Selected portion , I'd noticed that user can copy selected text. So my second question will be "Can we get the copied text?" I mean the copied portion should be saved somewhere in some environment variable, can we get it in c#?
You cannot bind selected text from WebBrowser but you can get it manually like so:
var doc = webBrowser.Document as mshtml.HTMLDocument;
if (doc != null)
{
var currentSelection = doc.selection;
if (currentSelection != null)
{
var selectionRange = currentSelection.createRange();
if (selectionRange != null)
{
var selectionText = selectionRange.Text;
//do something with selected text
}
}
}
where webBroswer is your browser control
<WebBrowser x:Name="webBroswer" ... />
but you'll need to add reference to Microsoft.mshtml and to answer your second question you can get copied text from clipboard with Clipboard class
var copiedText = Clipboard.GetText();

Edit a button by its given name

I am generating x amount of buttons and I give all of them a unique name.
After all those are generated, I want to edit one of them without regenerating them so I was wondering if I could get a component by its name?
I am using WinForms
Yes:
Control myControl = Controls.Find("textBox1");
Now, beware that you have to do proper casting hen found, because Find returns a control.
You can use Controls property of your form (or some container control on your form). With LINQ you can select buttons and then find first button with required name:
var button1 = Controls.OfType<Button>().FirstOrDefault(b => b.Name == "button1");
Or if you want to search child controls recursively
var button1 = Controls.Find("button1", true)
.OfType<Button>()
.FirstOrDefault();
Without LINQ you can use method Find(string key, bool searchAllChildren) of ControlCollection:
Control[] controls = Controls.Find("button1", true);
if (controls.Length > 0)
{
Button button1 = controls[0] as Button;
}
Button btn1 = (Button)(Controls.Find("btnName"));
This will get the required button and will save the button attributes into a new Button btn1
After all those are generated, I want to edit one of them without
regenerating them so I was wondering if I could get a component by its
name?
var myButton = Controls.Find("buttonName", true).FirstOrDefault(); //Gets control by name
if(myButton != null)
{
if (myButton.GetType() == typeof(Button)) //Check if selected control is of type Button
{
//Edit button here...
}
else
{
//Control isn't a button
}
}
else
{
//Control not found.
}
Make sure you add a reference to: linq.

How do I find out which button triggered the postback?

In asp.net (c#) how can I find out which asp:button triggered the postback?
I am using it for dynamic controls and want to do a different process on pageload for different buttons. I have tried looking at __EVENTARGUMENTS etc. but they didnt work.
I am looking to do something like this:
Page_load
Case:
Button 1 clicked
//Do something
Button 2 clicked
//Do something
Use the below code.
public static string GetPostBackControlId(this Page page)
{
if (!page.IsPostBack)
return string.Empty;
Control control = null;
// first we will check the "__EVENTTARGET" because if post back made by the controls
// which used "_doPostBack" function also available in Request.Form collection.
string controlName = page.Request.Params["__EVENTTARGET"];
if (!String.IsNullOrEmpty(controlName))
{
control = page.FindControl(controlName);
}
else
{
// if __EVENTTARGET is null, the control is a button type and we need to
// iterate over the form collection to find it
// ReSharper disable TooWideLocalVariableScope
string controlId;
Control foundControl;
// ReSharper restore TooWideLocalVariableScope
foreach (string ctl in page.Request.Form)
{
// handle ImageButton they having an additional "quasi-property"
// in their Id which identifies mouse x and y coordinates
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
controlId = ctl.Substring(0, ctl.Length - 2);
foundControl = page.FindControl(controlId);
}
else
{
foundControl = page.FindControl(ctl);
}
if (!(foundControl is Button || foundControl is ImageButton)) continue;
control = foundControl;
break;
}
}
return control == null ? String.Empty : control.ID;
}
Calling this function:
I have included the above function in a static class UtilityClass.
String postBackControlId = UtilityClass.GetPostBackControlId(this);
The code has been referenced from Mahesh's Blog.

Getting child entity as a type?

I'm trying to dynamically create objects, and then call from them later. For example...
for(int i=0;i<10;i++)
{
tabControl.TabPages.Add(i, i.ToString());
richTextBox rtb = new richTextBox();
rtb.Parent = tabControl.TabPages[i];
rtb.dock = fill;
}
then later in my coding..
private void onButtonClick_example()
{
var rtb = tabControl.SelectTab.GetChildrenByPoint(new point(1,1));
rtb.WordWrap = true;
}
How can I return that child as a "rich text box" again?
If GetChildrenByPoint returns something other than RichTextBox, then you need to use as and check for null so you don't crash when other controls are encountered.
foreach(var item in tabControl.SelectTab.GetChildrenByPoint(new point(1,1)))
{
RichTextBox rtb= item as RichTextBox;
if(rtb != null) //if we found a RichTextBox
{
rtb.WordWrap = true;
}
}
Add a dynamic ID to your rich text box control when you create it.
Loop through the controls in the selected tab:
foreach(var control in tabControl.SelectTab.Controls)
{
if(control.ID == "NEWCONTROLID")
{
RichTextBox rtb = (RichTextBox) control;
}
}
Did this off the top of my head, so there may be code issues, but hopefully it puts you on the path. Basically you need to search for the control you created in the controls collection of the selected tab, then cast it as a RichTextBox.
You could also use Control.Find() method to find your control and then cast it.

FrozenGridView in update panel is not accessable

I have a RealWorld.Grids.FrozenGridView and after selecting several checkboxes (in the last column) on the grid I try to access the rows in the C# file to run some tasks on the selected rows, but the grid comes up as null, and when I try to findcontrol from the page based on the name of the grid the result is null.
gridname = (RealWorld.Grids.FrozenGridView)this.FindControl("gridname") as RealWorld.Grids.FrozenGridView;
the grid is located in an updatepanel so to access the grid I include the update panel in the find control as such:
UpdatePanel up1 = new UpdatePanel();
up1.ID = "updatepanelID";
Label gn = (Label)up1.FindControl("labelname");
I also tried:
label lbl = (Label)this.Page.FindControl("updatepanelid").FindControl("labelname") as Label;
this should happen in a button_click event
Does anyone have any experience with this type of issue?
Any help is appreciated!
The FindControl doesn't always work as expected. Try this recursive function and use your line of code that you have up top.
public static Control FindControlRecursive(Control ctlRoot, string sControlId)
{
// if this control is the one we are looking for, break from the recursion
// and return the control.
if (ctlRoot.ID == sControlId)
{
return ctlRoot;
}
// loop the child controls of this parent control and call recursively.
foreach (Control ctl in ctlRoot.Controls)
{
Control ctlFound = FindControlRecursive(ctl, sControlId);
// if we found the control, return it.
if (ctlFound != null)
{
return ctlFound;
}
}// we never found the control so just return null.
return null;
}
Your call would look something like this.
var ridname = (RealWorld.Grids.FrozenGridView)FindControl(this, "gridname") as RealWorld.Grids.FrozenGridView;

Categories

Resources