Scroll to Position in RichTextBox - c#

I need help in scrolling to highlighted text/string positions in a rich text box. I was able to find text and highlight it but I want the user to be able to click on a Next button and that event to scroll to the vertical offset position of the first occurrence of the highlighted word to the next and so on after each click. Any help specifically with finding the position for the vertical offset of the line of the highlighted text would be helpful as well. Thanks in advance.

I found an answer to a similar question here. Below is the code that I believe will do the trick for you.
TextPointer start = txtEditor.Selection.Start;
FrameworkContentElement fce = (start.Parent as FrameworkContentElement);
if (fce != null)
{
fce.BringIntoView();
}

I had two TextPointers with which I created a TextRange, then used .ApplyPropertyValue on that to set background colour. Then I tried...
var fce = fromTextPointer as FrameworkContentElement;
if (fce != null)
fce.BringIntoView(); // unreliable
...but it was unreliable. What I eventually discovered worked - ostensibly reliably - was using the .Start of the TextRange I created from the same fromTextPointer:
var fce = textRange.Start.Parent as FrameworkContentElement;
if (fce != null)
fce.BringIntoView(); // ostensibly reliable
I would guess that certain actions - possibly the creation of a TextRange but more likely invocation of .ApplyPropertyValue - trigger enough position normalisation within the widget and/or textRange object that the .BringIntoView() is then reliable.
Perhaps this isn't necessary for the Selection - as in Wards answer - but I wasn't manipulating the Selection and this question doesn't mention the Selection specifically either, so posting here in-case it helps some other poor soul avoid hours of WPF "fun".

Related

How to set the Caret on the position of RightClick?

I have a RichTextBox with a SpellCheck implemented. I want to place the cursor/caret exactly where the rightclick is positioned. For example, if i have two misspelled words such as :
I belive this is wroking
and I right click on "belive", the context menu that opens is based on Wroking, because my cursor was last positioned there. To open the list of suggested words of "belive", I have to first Left click on the word, to position the caret and then RightClick.
So to make it clear, I want to automatically position the caret where my cursor is on RightClick. Is it possible to do that? Thanks in advance.
I Found a way to solve the problem, by getting the mouseposition on MouseRightButtonUp event and attributing it to a TextPointer. From there, I can select the exact Range of the current word, and then do something with it.
Point mousePoint = Mouse.GetPosition(textBox);
TextPointer current = textBox.GetPositionFromPoint(mousePoint, true);

MonoGame - Working With Specific Gestures for Different Purposes

Part of my particular dilemma is that I would like to be able to get the initial position of a drag gesture. Depending on the initial position of that drag gesture, the application would either 1) pan the view or 2) display a menu, but not perform these gestures at the same time (which is where part of struggle lies).
For example, if the user initiated a drag from the very left side of their screen and dragged inwards, a menu would pop in instead of the view panning.
I would also like to be able to execute a double tap gesture without also activating a tap gesture, if that's at all possible. I've tried working with boolean flags - for example,
// ...
if (gesture.GestureType == GestureType.DoubleTap)
{
isDoubleTap == true;
}
// ...
public static Vector2 Tap
{
get
{
if (!isDoubleTap)
return gesture.Position;
// ...
But that doesn't work.
I've tried using TouchCollection - if anyone would like me to elaborate on my issues with that I can, but for now I'll say what I tried hasn't worked. It's entirely possible I may have just goofed as I am a novice when it comes to working with touch input.
I've been working on this for a few days and have done as much searching as I can, and nothing I've found has alleviated my issue - if I happened to have missed something, I apologize.
Thank you for your time!
Concerning start position of a drag:
There is a gesture for a drag ending, so if you receive a drag and its the first one since the last drag ended, thats the initial position.
Concerning tap/doubletap:
MonoGame works the same way as XNA as documented here:
The user tapped the screen twice in quick succession. This
always is preceded by a Tap gesture.
This sounds like a input-bindings design problem more than a technical question imo. Consider also what you can move to instead occur on press or release rather than only making use of gestures.

Windows 8 App: "Snapping" Drag and Drop for Card Game

After trying to use the following snippet to move cards (Images right now) around I was not satisfied with the result.
Card.ManipulationDelta += (o, args) => {
var dragableItem = o as Image;
if (dragableItem == null) return;
var translateTransform = dragableItem.RenderTransform as TranslateTransform;
if (translateTransform == null) return;
translateTransform.X += args.Delta.Translation.X;
translateTransform.Y += args.Delta.Translation.Y;
};
Card.RenderTransform = new TranslateTransform();
The control had a funny behavior to be accelerated and would move / slide a bit after "dropping" it. Although cool I do not want this behavior and therefore changed my mind: what I am looking for is a solution to define specific areas for one active card, a bench for a few more cards and stacks for the deck, such that one can freely drag one card but it can only be dropped if it is above these certain areas otherwise it will get back to the area designated for the hand cards.
What could I try to implement this desired behavior?
I think you and I are in the same boat, I'm working on a Metro card game application and I'm not relly happy with what I've found as far as Drag and Drop goes. My inital approach was going to be to have a grid \ stackpanel or other underlying framework that the user could drag a card image ( acually a custom control ) over and then the image would snap to that framework when the user let go. I have not yet found a suitable way to obtain this behavior however because it seems like drag-drop of controls from one parent to another is not supported in Metro.
As far as your question goes, the sliding effect that you are refering to is most likely intertia, You can disable this by not setting the TranslateInertia mode, for example
Ellipse el = new Ellipse();
el.Fill = new SolidColorBrush(Windows.UI.Colors.Magenta);
el.ManipulationMode = (ManipulationModes.All ^ MainipulationModes.TranslateInteria);
//more code to add your ManipulationDelta handler etc.
You can also gain some control over the Interia by adding a handler for MainipulationInertiaStarting, though just setting e.Handled = true in the handler does not disable interia entirely for me as others have suggested.
I'd love to hear back from you and see what approach you've come up with for snapping cards, at this point I'm considering just using a large Canvas object and writing my own customer handlers for mouse moved to get card objects to be draggable and then snap into a row or other location on the playing board.
Cheers,
James

RichTextBox losing selection/caret position when changing underlying's FlowDocument's text

I've implemented "ChangeCase" keyboard shortcut (like Shift+F3 in MS WORD) for RichTextBox, which changes the text either selected by mouse, or the last word before caret's position. The problem is, it SOMETIMES loses the selection, or moves the caret one word left.
Once it changes the textcase without this changing of caret position, then it never changes the caret position (propably some WPF's internal caching.), so it can only happen the first time i run this function to a portion of text.
The code used is the solution mentioned in here WPF Flowdocument "change case" feature .
One problematic section of code is certainly
end = this.CaretPosition;
EditingCommands.MoveLeftByWord.Execute(null, this);
start = this.CaretPosition;
this.CaretPosition = end;
However I have no idea why it only occurs sometimes and how to fix this.
I thing it has something to do with the execution speed of this Execute() method and some side effects, because at my WPF app it only happens sometimes, but when hosting this WPF control in Winforms, moving the caret one word left happens all the time (if I hold Shift+F3, the cursor moves word by word to the very beginning of the document)
Other problem can be related with changing text of a TextRange, which is resulting in losing the selection? But again, it doesnt happen all the time and I have no clue how to fix it.
Any ideas?
I ended up with 2 options, ignoring this error or implementing the
MoveLeftByWord
logic manully without touching the
CaretPosition

WPF RichTextBox scroll to TextPointer

The WPF RichtTextBox has a method to scroll:
RichTextBox.ScrollToVerticalOffset(double)
I want to scroll in such a way, that a certain range or at least the start of it comes into view. How can I convert a TextPointer to double in a meaningful way?
Have a look at the FrameworkElement.BringIntoView Method. I'm using something like this:
public void Foo(FlowDocumentScrollViewer viewer) {
TextPointer t = viewer.Selection.Start;
FrameworkContentElement e = t.Parent as FrameworkContentElement;
if (e != null)
e.BringIntoView();
}
I'm somewhat late, but here is a more complete answer. The current scroll offsets need to be combined with the character position. Here is an example that scrolls RichTextBox text pointer to the center of the view:
var characterRect = textPointer.GetCharacterRect(LogicalDirection.Forward);
RichTextBox.ScrollToHorizontalOffset(RichTextBox.HorizontalOffset + characterRect.Left - RichTextBox.ActualWidth / 2d);
RichTextBox.ScrollToVerticalOffset(RichTextBox.VerticalOffset + characterRect.Top - RichTextBox.ActualHeight / 2d);
You don't need to check for negative numbers, as the scrolling accounts for this.
Use GetCharacterRect to get position of TextPointer in RichTextBox:
Rect r = textPointer.GetCharacterRect(LogicalDirection.Backward);
rtb.ScrollToVerticalOffset(r.Y);
So if you're wondering why BringIntoView() isn't working or it scrolls to the top of your textbox, it's likely because you are attempting to "bring into view" the Inline that comprises your entire scrollable text content - it "brings to view" this inline, which starts at (you guessed it) the "start" TextPosition at the top.
Solution is to use ScrollToVerticalOffset() per Miroslav's answer.

Categories