This question already has answers here:
Clicking HyperLinks in a RichTextBox without holding down CTRL - WPF
(7 answers)
Closed 3 years ago.
I must be missing something here. I've tried every possible way to make it so that anything is clickable inside a FlowDocument.
I've tried <Hyperlink> (along with every possible way to assign NavigateUri, RequestNavigate and even the Hyperlink.Click event - via XAML and pure code-behind), and I've tried placing a button in a <BlockUIContainer> which still doesn't work.
The content renders correctly but clicking it does nothing.
I've also tried removing all Style options so it's nothing more than a FlowDocument with 'stuff' in it, and have tried setting the RichTextBox to IsReadOnly=True/False. But no luck!
Example below. Where that <Hyperlink> is, I've tried all possibilities, e.g. <BlockUIContainer> etc. The end result is always that the element renders in the correct way, but clicking has no result at all.
//XAML
<RichTextBox IsReadOnly="True">
<FlowDocument>
<Paragraph>
1.1.3 Course technology requirements
</Paragraph>
<Paragraph>
<Run>
Access to an internet connection and a standard, modern web
browser are the only necessary requirements of the course.
If you are using an old or outdated browser, such as Internet
Explorer, you may need to update. We recommend
</Run>
<Hyperlink x:Name="GoogleChromeLink"
NavigateUri="https://www.google.com/chrome/"
RequestNavigate="Hyperlink_RequestNavigate" >
Google Chrome.
</Hyperlink>
</Paragraph>
</FlowDocument>
</RichTextBox>
// C#
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
Any pointers would be greatly appreciated. Thanks.
This solution saved the day: https://stackoverflow.com/a/6146387/5801881
I needed to add IsDocumentEnabled="True" to the RichTextBox element:
<RichTextBox IsDocumentEnabled="True" IsReadOnly="True">
Related
I'm trying to get the functionality to tab to the next text box once the user has input their data for the previous text box. For example, once they filled in a company name I'd like to be able to hit Tab and set the focus on the next text box "Job Name". Is this done in the code or the form properties?
Here is some of my code. I'm unsure how to nest a KeyEventsArgs within these, which is how I've seen others set the focus to the next text boxes using the KeyPress function.
private void textBox1_TextChanged(object sender, EventArgs e)
{
CompanyName = textBox1.Text;
textBox1.AcceptsTab = true;
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
JobName = textBox2.Text;
textBox2.AcceptsTab = true;
}
From the question you've asked and the code sample provided, there seems to be somewhat of a disconnect between your approach and the desired functionality.
As you would like the user to be able to use the Tab key in order to shift keyboard focus between elements in the window, you need only provide a TabIndex attribute on each of your TextBox controls. There is no need to use the TextChanged events to achieve this and it can be done completely in XAML for simplicity's sake.
From how I interpret your question, your next follow-on will likely be:
How do I initially give focus to a control when the application
starts?
To address this, there are a couple of alternatives available, simplest of which comes in the form of the FocusManager, which again I've illustrated usage of in XAML.
For convenience, here is a XAML-only implementation with TabIndex and FocusManager implemented:
<Window x:Class="tab_navigation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:tab_navigation"
mc:Ignorable="d"
Title="MainWindow" ResizeMode="NoResize" SizeToContent="WidthAndHeight" FocusManager.FocusedElement="{Binding ElementName=TbxCompanyName}">
<Grid Margin="10">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical" Margin="0,0,0,10">
<Label Content="Company Name:" Target="{Binding ElementName=TbxCompanyName}" />
<TextBox Name="TbxCompanyName" TabIndex="0" Width="160" HorizontalAlignment="Left"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<Label Content="Job Description:" Target="{Binding ElementName=TbxJobDescription}"/>
<TextBox Name="TbxJobDescription" TabIndex="1" Width="160" HorizontalAlignment="Left"/>
</StackPanel>
</StackPanel>
</Grid>
Give me a shout if you need any further help, although I would strongly recommend checking out some of the MSDN resources first, particularly those concerning Focus
UPDATE: In response to comment regarding implementing the solution,
WPF has a different design and best practices from that of WinForms.
I would strongly make the case that you cease using Forms and instead use a Window or UserControl derived class in place of a Form in your WPF project unless there is a very, very good reason for doing so. If you continue to use a Form inside of your WPF project, you will indeed need to implement your own keyboard navigation logic inside that form, and bridge various other gaps you'll inevitably run into when trying to get a Form behave in a commonly acceptable way.
I'll instead show you how you can achieve your request using an objectively better and more suitable approach in WPF-only, using Window or UserControl elements. There is also a complete solution zip downloadable here.
WPF is by design a lot more modular than WinForms and splits the areas of concerns nicely by default, although most developers implement a design pattern ontop of this; MVVM is the current darling of WPF, and does add quite a lot of value to a project, although it is outside the scope of your question, so I shall instead address the question itself on the grounds of how to achieve the request in its most basic forms. Do please be aware though that this is not the entirely ideal solution and I would strongly recommend you learn and implement the MVVM pattern for WPF if you are not already familiar with it.
With that disclaimer out of the way, instead of using a Form in WPF, its more useful for us to make a class which derives from Window. An even more common scenario in WPF would be that you would want to have a single window whose content changes between different views, rather than say creating multiple windows, although again that is outside the scope of the question and would rely upon reading into Binding and MVVM. I'm going to be showing you a quick and easy way to get the functionality you've asked for, I'm just trying to iterate here that this is not the norm almost all of the time.
To make a working solution, do the following to your project:
Right click your project in the solution explorer (presuming you are using Visual Studio)
'Add' a 'New Item...'.
Choose the 'Window (WPF)' template and name it. I'm going to call it CustomerInformationEntry from here out.
Open the CustomerInformationEntry.xaml file that has been created for us, remove the <Grid></Grid> tags and copy/paste this excerpt from the XAML I've already provided from above in their place:
<Grid Margin="10">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical" Margin="0,0,0,10">
<Label Content="Company Name:" Target="{Binding ElementName=TbxCompanyName}" />
<TextBox Name="TbxCompanyName" TabIndex="0" Width="160" HorizontalAlignment="Left"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<Label Content="Job Description:" Target="{Binding ElementName=TbxJobDescription}"/>
<TextBox Name="TbxJobDescription" TabIndex="1" Width="160" HorizontalAlignment="Left"/>
</StackPanel>
</StackPanel>
</Grid>
Add FocusManager.FocusedElement="{Binding ElementName=TbxCompanyName} to the Window element in CustomerInformationEntry.xaml.
This is our view or visual representation finished with now, and all that remains is to instanciate a new CustomerInformationEntry from our other Window or UserControl, and to then display it. In this case I'm going to be putting a button onto the MainWindow.xaml, and providing it a click event which will create the instance of our new Window:
In MainWindow.xaml add <Button Name="BtnOpenCustomerInformationEntry" Content="Enter Customer Information" Click="OpenCustomerInformationEntry"/>. In my case I'll be adding the button inside my object, although you can put it wherever you like if you've already created your initial window.
In MainWindow.xaml.cs we'll add a new private method which will be used by the Click event of your new button. Adding the following code:
private void OpenCustomerInformationEntry(object sender, RoutedEventArgs e)
{
CustomerInformationEntry myWindow = new CustomerInformationEntry();
myWindow.Show();
}
That's it, you now have a button in your MainWindow.xaml which when clicked uses the OpenCustomerInformationEntry method defined in MainWindow.xaml.cs, which in turn makes an instance of your CustomerInformationEntry window and displays it.
If you would still rather stick with the Forms approach, you can do that by using WindowsFormsHost, usage of which is discussed here.
Best Regards,
JC
I am trying to create an application to take notes for windows phone 8.1
I want to give the user,a notebook type of feel.
For this I have created the UI for notes, the XAML is:
<Grid Margin="0,12.333,0,-0.333">
<Grid.Background>
<ImageBrush ImageSource="Images/notebookpaper.jpg"/>
</Grid.Background>
<TextBox TextWrapping="Wrap" Background="{x:Null}" Text="" BorderBrush="{x:Null}" HorizontalAlignment="Left" Margin="60,96,0,0" VerticalAlignment="Top" Height="480" Width="340" BorderThickness="0" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" FontFamily="Arial" TextChanged="TextBox_TextChanged" AcceptsReturn="True" FontSize="24.8"/>
<TextBlock Text="Date : " HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Margin="246,10,0,0" Height="20" Width="59"/>
</Grid>
The image notebookpaper.jpg looks like this:
When user types in the text in text box, it looks like:
The problem is that, some characters appear a little above the line, some exactly on the line etc. which looks odd. Also, when I try to scroll, UI appears as:
The text appears striked out, as only the text scrolls and not the background image.
Also I want to be able to provide user a list of 5-6 fonts out of which they can select which one to use for typing the notes.
What should I do, so that the text appears properly aligned and text scrolls properly.
Is there any other way to do this ?
It looks like you have two problems:
Varying line height
Scrolling doesn't match the lines
To solve the first problem, you can probably work with TextBlock.TextLineBounds, talked about a bit in this MSDN blog post and the TextLineBounds enumeration documentation. This only seems to apply to TextBlocks, so you might have to swap between a TextBlock and TextBox as users edit their text.
To solve the second problem, the TextBox styles and templates page has a lot of helpful info. It looks like you can make your ImageBrush the background of your control by overriding TextBoxButtonBackgroundThemeBrush. If that doesn't work when focused, you may have to take the entire template given on the linked page and edit it to put your image in the background (there's a lot of XAML, but you should just be able to put your image in BackgroundElement or just before it).
If it still doesn't scroll, you can try setting ScrollViewer.Background instead; if that doesn't work, you'll need to handle the ScrollViewer.ViewChanging or ScrollViewer.ViewChanged events (probably by overriding it) so that it you can transform the background image by the amount of pixels the scrollviewer has moved.
You can also find the ScrollViewer in your code-behind (and skip dealing with the template) by using VisualTreeHelper. This would allow you to set the background of the ScrollViewer and/or subscribe to its events. This however is more brittle than the other methods and is usually a last resort.
I am working with some RichTextBlock objects that contain InlineUIContainer elements. I would like to be able to select and copy all of the text including the text contained in the InlineUIContainer.
Currently, when I select all of the text in the block, the text contained in the InlineUIContainer objects are skipped.
Here is an example of what I'm creating:
<RichTextBlock IsTextSelectionEnabled="True">
<Paragraph FontSize="20">
<Bold>This text is selectable</Bold>
<InlineUIContainer FontFamily="Global User Interface">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="11" VerticalAlignment="Top" Margin="0,0,-1,0">Super Script Text</TextBlock>
<HyperlinkButton ClickMode="Release" Style="{StaticResource NoMarginHyperlinkButtonStyle}">
Link
</HyperlinkButton>
</StackPanel>
</InlineUIContainer>
This text is also selectable
</Paragraph>
</RichTextBlock>
If I select all of the text from this piece of Xaml and copy/paste it in NotePad, I don't get the Super Script Text or the Link text.
Is there any way to get all of the text selected?
This is because HyperlinkButton is not part of the document API and in fact a UIElement wrapped in InlineUIContainer. There are 2 ways to handle this.
Switch to Windows 8.1 and Hyperlink which inherits from TextElement and copy will work just fine.
This is the hard way, if you must support this in Windows 8.
Remove the default Context menu items for the RichTextBlock and replace with your own Copy Command. Which should get the 2 TextPointers i.e. RichtextBlock.SelectionStart and RichTextBlock.SelectionEnd
Now with WPF we could get a TextRange within this range but winRT does not expose it, so you will need to do it in your code...
Get all the block within the RichTextBlock, and iterate through each to check if it's ContentStart and ContentEnd is within the RTB.SelectionStart and RTB.SelectionEnd if so then add them to a list.
Now it should be easy to extract all the Runs and Bold/Italics from this list and any InlineUIContainers hosting HyperlinkButtons.
2 This is not really a good way to go as it will be hard to allow for margins etc. on Paragraphs etc.
This is my first day to design UI using WPF. I have looked up MSDN official document of Flow Document and found that I can place an UI control inside a RichTextBox. I did put a button in but found it's not interactable - I cannot click on it as it's grey. And I also tried other controls and they all displayed fine but just don't support interaction. Even a hyperlink doesn't work.
I have searched over internet, the closest question ever asked is about how to make an inside hyperlink click-able: The similar question: C# WPF Text with links
I did the same thing but it didn't work! All component displayed well but just are not able to be clicked.
Here is my XAML code:
<RichTextBox Grid.Row="1" Margin="14.007,31.067,22.011,46.305" Name="rtxtRslt" BorderBrush="White" >
<FlowDocument>
<Section FontSize="15">
<Paragraph>
<Bold>Click on this:</Bold>
<Italic><Hyperlink NavigateUri="http://stackoverflow.com">http://www.jxitc.info</Hyperlink></Italic>
</Paragraph>
<BlockUIContainer>
<Button Click="Button_Click">Also Click On This</Button>
</BlockUIContainer>
</Section>
</FlowDocument>
</RichTextBox>
Can anyone give me some suggestion:
1. is it possible to make it click-able
2. if yes, if I forgot to set any/what attribution of the RichTextBox control?
First off your direct question: how to make the content of the RichTextBox "active". Set the IsDocumentEnabled property to True on the RichTextBox like shown here:
<RichTextBox Grid.Row="1" Margin="14.007,31.067,22.011,46.305" Name="rtxtRslt" BorderBrush="White"
IsDocumentEnabled="True">
<FlowDocument>
<Section FontSize="15">
<Paragraph>
<Bold>Click on this:</Bold>
<Italic>
<Hyperlink NavigateUri="http://stackoverflow.com">http://www.jxitc.info</Hyperlink>
</Italic>
</Paragraph>
<BlockUIContainer>
<Button Click="Button_Click" >Also Click On This</Button>
</BlockUIContainer>
</Section>
</FlowDocument>
</RichTextBox>
Now to the unspoken question: do you have to be in a RichTextBox at all? The fact that there is a special property on the RichTextBox to make embedded UI elements active kinda indicates that is not the normal usage for this control. It is meant to host editable FlowDocument content. So the user of the RichTextBox would typically be creating the document that hosts the button that a consumer of the document could click, if that helps make the distinction clear I don't know.
However, all that being said, your FlowDocument hosted instead in a simple FlowDocumentPageViewer is active by default.
<FlowDocumentPageViewer>
<FlowDocument>
<Section FontSize="15">
<Paragraph>
<Bold>Click on this:</Bold>
<Italic>
<Hyperlink NavigateUri="http://stackoverflow.com">http://www.jxitc.info</Hyperlink>
</Italic>
</Paragraph>
<BlockUIContainer>
<Button Click="Button_Click" >Also Click On This</Button>
</BlockUIContainer>
</Section>
</FlowDocument>
</FlowDocumentPageViewer>
Now to the other unspoken question (unspeakable?) do you have to be in FlowDocument content at all? FlowDocument content is similar to, but not derived from UIElement. As such, many of the out-of-the-box features of UIElements are not available. If you need document functionality in the UI FlowDocuments can provide a great start but bring with them a pretty big learning curve in their own right.
The title of your question, if taken literally, makes me think you might just want a WPF UI that allows you to embed Buttons and Hyperlinks and have them work (gasp). That is certainly the default behavior. If you do not need the document look and feel that FlowDocument provides nor the real time document editing that RichTextBox provides you might consider a more "traditional" WPF layout.
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch"
Margin="20">
<TextBlock>
<Bold>Click on this:</Bold>
<Italic>
<Hyperlink NavigateUri="http://stackoverflow.com">http://www.jxitc.info</Hyperlink>
</Italic>
</TextBlock>
<Button Click="Button_Click"
Margin="0,20,0,0">Also Click On This</Button>
</StackPanel>
I am having a WPf hyperlink inside a WPf Richtextbox , clicking on hyperlink results in opening of a popup.
But i wish to prevent the editing of hyperlink text.
Initially it looks like below
but when user edits the hyperlink it looks like this
So I wish to prevent this editing of hyerlink.
If you add in a container it cannot be edited (but removed as a whole):
<InlineUIContainer>
<TextBlock>
<Hyperlink NavigateUri="http://www.google.com/">
<Run Text="Google"/>
</Hyperlink>
</TextBlock>
</InlineUIContainer>
Would this be any good?