Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
480
ContentPane with RichTextBox
posted

Hi,

When placing a RichTextBox inside a ContentPane, the functionality selecting a text typed inside the RichTextBox works fine. But when right clicking on the selected text and invoking the context menu the selection on the text gets unselected. And again after the context menu is dismissed the text selection that was lost gets selected again.

This is not the behavior when placing the RichTextBox on a StackPanel or a Grid.

Is this an intended behavior or a bug in ContentPane. Is there a workaround to resolve this issue.

-Alex

Parents Reply
  • 54937
    Offline posted in reply to Luke Wisniewski

    I don't recall (certainly not 6 years ago when the control was first written but even now) MS' documentation stating that this is for temporary focus - after all it is set to true on a Window. The documentation (IsFocusScope and Input Overview) basically describes the property as being a means for making an element a container that tracks the focused element within that element. Even when keyboard focus is no longer within that element, the FocusedElement is still considered logically focused. This is basically why the property was made true for ContentPanes - because each pane is really an isolated group of elements where the focus for each should be maintained separately. One could make arguments for why it should or should not be true in this case but I won't get into that. Instead I'll just mention the implications of having this true or not (at least the ones I know since this property is used/referenced internally by some MS controls and assumptions made based on that) and you can decide whether you want to change it to false.

    So having IsFocusScope set to true will mean that the FocusedElement of the FocusScope (the ContentPane in this case) will be used to store a reference to the logically focused element within that scope. So when a pane is re-activated, focus will be shifted back to that FocusedElement (basically the last element within that had keyboard focus). In addition, the Got/LostFocus events are based upon logical focus. So if an element within a pane has keyboard focus and you shift focus to another focusscope (i.e. another pane, another window, the content of the xamdockmanager, etc.) that element's LostFocus events will not be triggered and if one had a binding on that element with an UpdateSourceTrigger of LostFocus (the TextBox's Text property does this by default) then the binding will not be updated either. That is until you shift focus to another element within that focusscope (again the pane in this case). So setting IsFocusScope to false would mean that shifting focus to any other element in that window will cause it to lose logical focus and its LostFocus event will fire and any LostFocus UpdateSourceTrigger bindings will update the source. Notice I said within that window because shifting focus to an element in another window (even if that is a floating pane since in a standard wpf application that is hosted within a window) that element will still be the logically focused element since it will be the FocusedElement of the Window.

    The focus scope also has an impact on the routing of RoutedCommands. When routing the CanExecute and Execute events of a RoutedCommand, the WPF CommandManager checks if an element is a focus scope. If it is then it will re-route the events through the FocusedElement of that focus scope. So if for example you had a Toolbar within a ContentPane and you had some RoutedCommands associated with the buttons in that toolbar, the CanExecute/Execute would (by default) route up the visual tree until it hits the Toolbar. The CommandManager would then see that the Toolbar is a focus scope and it would get the containing focus scope and get the focused element of that and start routing the CanExecute/Execute through that element. So if the IsFocusScope of the pane is true that will always route through the last focused element within that pane. If IsFocusScope were false then the parent focus scope would likely be the window and it would route to whatever is the logically focused element there - which may be in that pane, some other pane or some other element within the window.

    Unfortunately there are also a number of elements within the framework that make certain assumptions based on the FocusScope. For example a ButtonBase assumes that if it is not in the root focus scope (i.e. if the visual parent of the button's focus scope is non-null) that it should shift keyboard focus out of the focus scope when the button is clicked (if it has keyboard focus when it loses capture anyway). The ContentPane works around this assumption. Also, elements like Selector (e.g. ListBox), TextBoxBase and TreeView assume that if they lose keyboard focus and the element that received keyboard focus is in not the focused element of the root focus scope (e.g. the Window or ElementHost) that they should continue to display their selection as if active. This was done to try and keep the selection showing as active (e.g. blue) when you dropped down a menu, etc. It would have been better if MS has another property so an element could indicate it should be considered "root" focus scope in which case both of these issues could have been avoided.

Children