How to make <UIElement> interactable or click-able in WPF UI - c#

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>

Related

Stop Screen Reader to read my control type in WPF

I have an old WPF application with needs and accessibility features. The application uses radio buttons to construct a menu with a popup.
The problem is the user doesn't want the narrator to say "radio button" when it's clicked. I am using AutomationProperties.HelpText and AutomationProperties.Name to adjust the text for the controls. I have no idea how to change the "ControlType" the narrator reads out when the control is in focus.
<RadioButton
AutomationProperties.AcceleratorKey="1"
AutomationProperties.AccessKey="3"
AutomationProperties.AutomationId="2"
AutomationProperties.HelpText="Taufiq"
AutomationProperties.ItemStatus="Test"
AutomationProperties.ItemType="Text"
AutomationProperties.Name="Take Snapshot"
Command="{Binding TakeSnapshotCommand}">
<StackPanel Orientation="Horizontal">
<ContentControl Content="{DynamicResource GalleryIcon}" Focusable="False" />
<TextBlock Text="Take Snapshot" />
</StackPanel>
</RadioButton>
None of the properties of the AutomationProperties works.
My understanding is that narrator will read the advertised type so that someone relying on the screen reader knows how to interact with the focussed item.
If you really need to control how this works, you'll need to subclass RadioButton and override OnCreateAutomationPeer to create your own peer which can then gain quite a bit of control.

WPF interactive content (button, hyperlink etc) never works inside FlowDocument [duplicate]

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">

Notebook-like background for a TextBox in a Windows Phone App

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.

Copying Xaml RichTextBlock text with InlineUIContainers

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.

How to "float" image in XAML (Windows 8 Metro)

Is it possible to do in XAML something like ffloat:left for an image in CSS. I need to create something like this:
with variable image dimensions and text length.
Edit: The text warp around the image is not static in my case, it is create in C# code that returns a list of TextBlock elements (with Runs)
With Silverlight 4 you would achieve this using a RichTextBox:
<RichTextBox TextWrapping="Wrap" IsReadOnly="False">
<Paragraph>
More text here ..
<InlineUIContainer>
<Image Source="abc.jpg"/>
</InlineUIContainer>
more and more text here;
<LineBreak />
</Paragraph>
</RichTextBox>
It looks like Win8 Metro has a RichTextBox, and also has an InlineUIContainer, so something like the above should work!
The solution seems to be using RichTextBlockOverflow and OverflowContentTarget described in this presentation: http://video.ch9.ms/build/2011/slides/APP-914T_Street.pptx
This question seems to be asking for something similar to what you want. The answer here should prove a solution to what you desire.
A summary of the answer is, use a FlowDocument like the following example:
<FlowDocument>
<Paragraph>
<Floater HorizontalAlignment="Left">
<BlockUIContainer>
<Image Source="/FlowDocumentTest;component/dog.png" Width="100" />
</BlockUIContainer>
</Floater>
Here is where the text goes to wrap around the image.
</Paragraph>
</FlowDocument>
Update
As your question states, you are now using some C# code to generate TextBlock/Run Elements, both can be children of a Paragraph object. So simply name your Paragraph like so:
<FlowDocument>
<Paragraph x:Name="textPara">
<Floater HorizontalAlignment="Left">
<BlockUIContainer>
<Image Source="/FlowDocumentTest;component/dog.png" Width="100" />
</BlockUIContainer>
</Floater>
</Paragraph>
</FlowDocument>
Then in C#, add your generated TextBlocks or Runs to the Inlines property of textPara, i.e.
var runToInsert = new Run("Some text to display");
textPara.Inlines.InsertAfter(textPara.Inlines.FirstInline, runToInsert);

Categories