Getting selected text from a RichTextBox only on MouseUp? - wpf

I'm a newbe to RichTextBox and unable to find the answer. In a RichTextBox (WPF) that is already holding text content, I would like to be able to place the cursor down on one letter; move the cursor horizontally while holding it down; then lift the cursor up. This results in the text being highlighted and selected. So far so good.
However, in the following XAML, the selection event is triggered for every character. I only want one firing for when the mouse is lifted off the box and ultimately would like to know the starting and ending insertion points for the selected text as well as the selected text. (I know this is simple, but I can't get it :( ).
XAML
<SimpleRichTextBox Name="simplerichtextbox" Grid.Column="1"
RichText="{Binding RichText, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
SelectionChanged="simplerichtextbox_SelectionChanged"
>
<FlowDocument PageWidth="{Binding ElementName=simplerichtextbox, Path=ActualWidth}" />
<SimpleRichTextBox>
Any help is much appreciated.

Related

XAML - Relatively Position Control Outside of Document Flow

I'm looking to create a UI element in a WPF XAML UserControl with something that looks and works roughly like Google Suggest - a TextBox with a ListBox that appears beneath it showing suggestions that match the text entered in the TextBox. In simplified form, my XAML looks like this:
<StackPanel>
[...controls above...]
<TextBox ... />
<ListBox ItemsSource="{Binding SearchHints}"
Visibility="{Binding HasSearchHints}" MaxHeight="100" />
[...controls below...]
</StackPanel>
What I'm struggling to achieve is I want the ListBox to float above any content that may come below it, much like the dropdown part of a ComboBox does. Currently it pushes any controls below it downwards. I figure this must be possible because the ComboBox control essentially does exactly what I want to do. In CSS it would be a matter of setting the element to position:relative but there doesn't seem to be an immediately obvious equivalent in XAML. Any ideas?
Used Icepickle's comment - the element did exactly what I wanted.

WPF ComboBox using shortcut keys for selecting items

I have a combo box in WPF that uses the following data template. With help from the forum I was able to get this to display and behave properly.
When the drop down is open I would like the user to be able to type a letter and have the drop down skip to that selection. I have seen this implemented two ways, one where it bascially captures the keyboard input in a text box in the combo box and selects based on what the user has typed. This allows the user to wait and type more text that gets add to the criteria. The other is where the keyboard input doesn't appear to get captured anywhere, if yo type a letter, wait a couple seconds and type another letter it takes you to the selection starting with the second letter you typed. If you want to type multiple letters of the search criteria you have to type them quickly together.
I'd be happy with either approach. They can only select an item though that is in the list, so I don't really like the idea of putting an edit control on the combo box where they can type in whatever they want. I could do this and than validate their input, but would rather force them to select something that is in the list.
In this case it is a list of system colors, which is over 140 of them, so having a way to quickly get around the list is what I need.
Here is my data template that I am using.
<DataTemplate x:Key="ColorSelectionComboBox" DataType="ComboBox">
<StackPanel Orientation="Horizontal">
<Rectangle Width="16" Height="16" Margin="0,2,4,2">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Color}"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
Any ideas are appreciated.
ComboBox has built-in support for incremental search using the keyboard. I haven't actually used it (so I'm no good for help with advanced troubleshooting) but I know it's there.
It looks like you need to set the ComboBox's IsTextSearchEnabled property to true, and then set the TextSearch.TextPath attached property to the binding path of the text you want to search on (probably "Name" to correspond with your TextBlock text).

WP7 -- Context Menu Forces Black Background for Listbox

This is probably an easy one... I have a Listbox with a ContextMenu embedded in it, and every time the ContextMenu appears, the Listbox changes its background to opaque black. How do I prevent this from happening?
Here is some sample XAML:
<ListBox x:Name="FolderItems" ItemTemplate="{StaticResource ItemTemplate}" ItemContainerStyle="{StaticResource ItemListBox}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" ItemsSource="{Binding FolderItems}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu
x:Name="FolderContextMenu"
Margin="20"
Background="WhiteSmoke"
BorderBrush="Black"
BorderThickness="1.0"
Closed="ContextMenu_Closed">
<toolkit:MenuItem Loaded="ContextMenuItem_Loaded"
Opacity="0.0" Margin="5" Background="Transparent"
Click="ContextMenuItem_Click" Name="ContextMenuDelete">
<toolkit:MenuItem.Header>
<TextBlock Text="delete" FontFamily="Segoe WP Bold"/>
</toolkit:MenuItem.Header>
</toolkit:MenuItem>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</ListBox>
Thanks
Update
I still haven't figured out why the entire listbox goes black when the context menu appears. I've set everything I can think of to a transparent brush.
I fixed this for my situation by opening up the toolkit (downloading the source: Silverlight Toolkit), and editing the color values myself in ContextMenu.cs . Then, I rebuilt and targeted the dll that I created rather than the one from the installer.
The only issue is that I will now need to do this application specific, but at least I can have a resolution. I believe also that if you set IsZoomEnabled=false, it won't have this behavior in the first place, but it's a different experience.
Here's my edited version: Pastebin
Check out the lines like this, they're the ones you'll need to change:
// Create a layer for the element's background
UIElement elementBackground = new Rectangle
{
Width = ownerElement.ActualWidth,
Height = ownerElement.ActualHeight,
Fill = new SolidColorBrush(Colors.White),
};
Good luck!
There's a simple way to do this. For some reason MS Access complements the colors when using a list box. If you set the foreground to red, it will show green, etc.
So, set the background color to black (0) and the foreground color to white (16777215). Counter-intuitive but it works is MS Access 2002.
Without seeing the template you're using I can't say for sure but you've probably hardcoded a background value but not considered the different states of the list items and the default state colour/value is being displayed

WPF: Use SpellCheck On Read-Only TextBox

I'm looking to display text with the wavey red lines where a word is misspelt, but I only want the text to be selectable, not editable. If I set the TextBox's IsReadOnly property to True or IsEnabled to False, the wavey red lines disappear and I can't get around it by putting something transparent as this will prevent the user being able to select sections of the text.
Is there anyway I can keep the red lines, allow the text to be selectable but prevent the actual text being modified?
Thanks
You could hook up to on the text change event of the text box, and just reject the new text. It would have the same effect of readonly without graying out the textbox or getting rid of the spell checking.
Thanks David. I'm currently looking at 2 possible solutions, yours and the following:
I've created a custom control which is based on the standard TextBox, but effectively has 2 textboxes laid on top of one another in this manor:
<TextBox Name="tbxBack"
Foreground="Transparent"
SpellCheck.IsEnabled="True"
TextWrapping="Wrap"
SnapsToDevicePixels="True"/>
<TextBox Name="tbxFront"
Background="Transparent"
TextWrapping="Wrap"
SnapsToDevicePixels="True"
IsReadOnly="True"/>
I think it's pretty straight forward what's going on here, but I'm concerned about the potential overhead this will cause.
The reason I'm looking into the double TextBox solution is that I'm worried if I try and cancel the event, it could end up with some sort of flashing in the control when the text is changed.

Display images in TextBlock (WPF)

I'm working on a simple chat application. Currently the messages are binded to a custom-styled listbox like this (simplified XAML):
<ListBox ItemsSource="{Binding MessageCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now I would like to be able to put images (like graphical smileys) into the displayed message text. Is there any way to achieve this using TextBlock (or any other standart component) or do I need to use some special control for this?
Thanks in advance
Just use the InlineUIContainer.
<TextBlock TextWrapping="Wrap">
<Run>Some text.</Run>
<InlineUIContainer>
<Image Source="http://sstatic.net/stackoverflow/img/apple-touch-icon.png" Height="20"></Image>
</InlineUIContainer>
<Run>Some more text.</Run>
</TextBlock>
The Content of a TextBlock is always just a series of Inlines, so you should use the InlineUIContainer. You can insert this container as one of the Inlines in your TextBlock wherever you want an Image to appear, alternating with text Runs. You could parse a message and at the same time keep adding the tokens (either text or images) that you find to the Inlines collection of the TextBlock.
If you want the Images actually inside the text (like an emoticon), then you are going to have to do some work. This sounds like one of the few times I would actually want a User Control, the point of which would be one that scans the Text looking for emoticon values and building a Data Template on the fly.
Remember that anything you can do in XAML you can do in code, so the code I'm thinking of would follow this general idea:
Scan text for emoticon values and
create a list of values for data
elements.
Create a DockPanel.
Foreach element in the List, add
either a TextBlock or an Image
(based on value).
Set this.Content to the DockPanel.
I think something like this is actually what you are looking for, but if you want just an Image, then the ValueConverter suggestion would work.
You could use a value converter to convert the text to another type which has a list of segments which are composed of either text or the smiley face (in the order in which they appear).
Then, you can use a data template to bind to that new type and display the text and smiley faces appropriately.
I also encountered this problem recently and I overcome this by
Creating an ListBox ItemTemplate containing an ItemsControl that has a WrapPanel in the ItemsPanelTemplate and then binding my string to the ItemsSource of the ItemsControl with a IValueConverter that houses all the logic.
Split out your words and query/search your emoticons strings, hyperlinks etc and create your TextBlock, Image, Hyperlink, Button elements and set your values and event handles.
In the function create a List<UIElement> and populate the List with the controls you have generated and return the List as the object in the Convert function of the IValueConverter.
Because you have the WrapPanel in there you get your wrapping done.
Use the Image element instead of the TextBlock and use a Converter to map the text value to the smile image.
<ListBox ItemsSource="{Binding MessageCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Text, Converter={StaticResource MyImageConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>

Resources