<toolkit:RichTextBox>
<toolkit:RichTextBoxFormatBarManager.FormatBar>
<toolkit:RichTextBoxFormatBar />
</toolkit:RichTextBoxFormatBarManager.FormatBar>
</toolkit:RichTextBox>
or on the default RichTextBox like so
<RichTextBox >
<toolkit:RichTextBoxFormatBarManager.FormatBar>
<toolkit:RichTextBoxFormatBar />
</toolkit:RichTextBoxFormatBarManager.FormatBar>
</RichTextBox>
You can also create your own format bar by inheriting from IRichTextBoxFormatBar.
pull/1645/head
@ -1,107 +0,0 @@ |
|||||
using System; |
|
||||
using System.Windows.Controls; |
|
||||
using System.Windows.Documents; |
|
||||
using System.Windows; |
|
||||
|
|
||||
namespace Microsoft.Windows.Controls.Formatting |
|
||||
{ |
|
||||
internal class FormatToolbarManager |
|
||||
{ |
|
||||
RichTextBox _richTextBox; |
|
||||
readonly UIElementAdorner<Control> _adorner; |
|
||||
FormatToolbar toolbar; |
|
||||
|
|
||||
bool AdornerIsVisible |
|
||||
{ |
|
||||
get { return _adorner.Visibility == Visibility.Visible; } |
|
||||
} |
|
||||
|
|
||||
public FormatToolbarManager(RichTextBox richTextBox) |
|
||||
{ |
|
||||
_richTextBox = richTextBox; |
|
||||
_adorner = new UIElementAdorner<Control>(richTextBox); |
|
||||
toolbar = new FormatToolbar(richTextBox); |
|
||||
AttachToRichtextBox(); |
|
||||
} |
|
||||
|
|
||||
private void AttachToRichtextBox() |
|
||||
{ |
|
||||
_richTextBox.Selection.Changed += Selection_Changed; |
|
||||
} |
|
||||
|
|
||||
void Selection_Changed(object sender, EventArgs e) |
|
||||
{ |
|
||||
TextRange selectedText = new TextRange(_richTextBox.Selection.Start, _richTextBox.Selection.End); |
|
||||
if (selectedText.Text.Length > 0) |
|
||||
{ |
|
||||
VerifyAdorner(); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
HideAdorner(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
//TODO: refactor
|
|
||||
void VerifyAdorner() |
|
||||
{ |
|
||||
VerifyAdornerLayer(); |
|
||||
|
|
||||
Control adorningEditor = toolbar; |
|
||||
_adorner.Child = adorningEditor; |
|
||||
_adorner.Visibility = Visibility.Visible; |
|
||||
|
|
||||
Rect wordBoundary = _richTextBox.Selection.End.GetPositionAtOffset(0, LogicalDirection.Backward).GetCharacterRect(LogicalDirection.Backward); |
|
||||
|
|
||||
double left = wordBoundary.X; |
|
||||
double top = (wordBoundary.Y + wordBoundary.Height) - toolbar.ActualHeight; |
|
||||
|
|
||||
//top boundary
|
|
||||
if (top < 0) |
|
||||
{ |
|
||||
top = wordBoundary.Y + wordBoundary.Height; |
|
||||
} |
|
||||
|
|
||||
//right boundary
|
|
||||
if (left + toolbar.ActualWidth > _richTextBox.ActualWidth - 20) |
|
||||
{ |
|
||||
left = left - toolbar.ActualWidth; |
|
||||
top = wordBoundary.Y + wordBoundary.Height + 5; |
|
||||
} |
|
||||
|
|
||||
//bottom boundary
|
|
||||
if (top + toolbar.ActualHeight > _richTextBox.ActualHeight - 20) |
|
||||
{ |
|
||||
top = wordBoundary.Y - (toolbar.ActualHeight + wordBoundary.Height); |
|
||||
} |
|
||||
|
|
||||
_adorner.SetOffsets(left, top); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Ensures that the adorner is in the adorner layer.
|
|
||||
/// </summary>
|
|
||||
/// <returns>True if the adorner is in the adorner layer, else false.</returns>
|
|
||||
bool VerifyAdornerLayer() |
|
||||
{ |
|
||||
if (_adorner.Parent != null) |
|
||||
return true; |
|
||||
|
|
||||
AdornerLayer layer = AdornerLayer.GetAdornerLayer(_richTextBox); |
|
||||
if (layer == null) |
|
||||
return false; |
|
||||
|
|
||||
layer.Add(_adorner); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
void HideAdorner() |
|
||||
{ |
|
||||
if (this.AdornerIsVisible) |
|
||||
{ |
|
||||
_adorner.Visibility = Visibility.Collapsed; |
|
||||
_adorner.Child = null; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,9 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Microsoft.Windows.Controls |
||||
|
{ |
||||
|
public interface IRichTextBoxFormatBar |
||||
|
{ |
||||
|
global::System.Windows.Controls.RichTextBox RichTextBox { get; set; } |
||||
|
} |
||||
|
} |
||||
|
Before Width: | Height: | Size: 175 B After Width: | Height: | Size: 175 B |
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
|
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 183 B |
|
Before Width: | Height: | Size: 169 B After Width: | Height: | Size: 169 B |
|
Before Width: | Height: | Size: 186 B After Width: | Height: | Size: 186 B |
|
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 181 B |
|
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 197 B |
@ -0,0 +1,177 @@ |
|||||
|
using System; |
||||
|
using System.Windows; |
||||
|
using System.Windows.Controls; |
||||
|
using System.Windows.Documents; |
||||
|
using Microsoft.Windows.Controls.Core; |
||||
|
|
||||
|
namespace Microsoft.Windows.Controls |
||||
|
{ |
||||
|
public class RichTextBoxFormatBarManager : DependencyObject |
||||
|
{ |
||||
|
#region Members
|
||||
|
|
||||
|
private global::System.Windows.Controls.RichTextBox _richTextBox; |
||||
|
private UIElementAdorner<Control> _adorner; |
||||
|
private IRichTextBoxFormatBar _toolbar; |
||||
|
|
||||
|
#endregion //Members
|
||||
|
|
||||
|
#region Properties
|
||||
|
|
||||
|
#region FormatBar
|
||||
|
|
||||
|
public static readonly DependencyProperty FormatBarProperty = DependencyProperty.RegisterAttached("FormatBar", typeof(IRichTextBoxFormatBar), typeof(RichTextBox), new PropertyMetadata(null, OnFormatBarPropertyChanged)); |
||||
|
public static void SetFormatBar(UIElement element, IRichTextBoxFormatBar value) |
||||
|
{ |
||||
|
element.SetValue(FormatBarProperty, value); |
||||
|
} |
||||
|
public static IRichTextBoxFormatBar GetFormatBar(UIElement element) |
||||
|
{ |
||||
|
return (IRichTextBoxFormatBar)element.GetValue(FormatBarProperty); |
||||
|
} |
||||
|
|
||||
|
private static void OnFormatBarPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
||||
|
{ |
||||
|
global::System.Windows.Controls.RichTextBox rtb = d as global::System.Windows.Controls.RichTextBox; |
||||
|
if (rtb == null) |
||||
|
throw new Exception("A FormatBar can only be applied to a RichTextBox."); |
||||
|
|
||||
|
RichTextBoxFormatBarManager manager = new RichTextBoxFormatBarManager(); |
||||
|
manager.AttachFormatBarToRichtextBox(rtb, e.NewValue as IRichTextBoxFormatBar); |
||||
|
} |
||||
|
|
||||
|
#endregion //FormatBar
|
||||
|
|
||||
|
bool AdornerIsVisible |
||||
|
{ |
||||
|
get { return _adorner.Visibility == Visibility.Visible; } |
||||
|
} |
||||
|
|
||||
|
#endregion //Properties
|
||||
|
|
||||
|
#region Event Handlers
|
||||
|
|
||||
|
void RichTextBox_SelectionChanged(object sender, EventArgs e) |
||||
|
{ |
||||
|
TextRange selectedText = new TextRange(_richTextBox.Selection.Start, _richTextBox.Selection.End); |
||||
|
if (selectedText.Text.Length > 0 && !String.IsNullOrWhiteSpace(selectedText.Text)) |
||||
|
{ |
||||
|
ShowAdorner(); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
HideAdorner(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endregion //Event Handlers
|
||||
|
|
||||
|
#region Methods
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Attaches a FormatBar to a RichtextBox
|
||||
|
/// </summary>
|
||||
|
/// <param name="richTextBox">The RichtextBox to attach to.</param>
|
||||
|
/// <param name="formatBar">The Formatbar to attach.</param>
|
||||
|
private void AttachFormatBarToRichtextBox(global::System.Windows.Controls.RichTextBox richTextBox, IRichTextBoxFormatBar formatBar) |
||||
|
{ |
||||
|
_richTextBox = richTextBox; |
||||
|
_richTextBox.PreviewMouseMove += RichTextBox_PreviewMouseMove; |
||||
|
_richTextBox.Selection.Changed += RichTextBox_SelectionChanged; |
||||
|
|
||||
|
_adorner = new UIElementAdorner<Control>(_richTextBox); |
||||
|
|
||||
|
formatBar.RichTextBox = _richTextBox; |
||||
|
_toolbar = formatBar; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void RichTextBox_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e) |
||||
|
{ |
||||
|
//if the mouse moves outside the richtextbox bounds hide the adorner
|
||||
|
//though this deosn't always work, especially if the user moves the mouse very quickly.
|
||||
|
//need to find a better solution, but this will work for now.
|
||||
|
Point p = e.GetPosition(_richTextBox); |
||||
|
if (p.X <= 5.0 || p.X >= _richTextBox.ActualWidth - 5 || p.Y <= 3.0 || p.Y >= _richTextBox.ActualHeight - 3) |
||||
|
HideAdorner(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Shows the FormatBar
|
||||
|
/// </summary>
|
||||
|
void ShowAdorner() |
||||
|
{ |
||||
|
VerifyAdornerLayer(); |
||||
|
|
||||
|
Control adorningEditor = _toolbar as Control; |
||||
|
_adorner.Child = adorningEditor; |
||||
|
_adorner.Visibility = Visibility.Visible; |
||||
|
|
||||
|
PositionFormatBar(adorningEditor); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Positions the FormatBar so that is does not go outside the bounds of the RichTextBox or covers the selected text
|
||||
|
/// </summary>
|
||||
|
/// <param name="adorningEditor"></param>
|
||||
|
private void PositionFormatBar(Control adorningEditor) |
||||
|
{ |
||||
|
Rect wordBoundary = _richTextBox.Selection.End.GetPositionAtOffset(0, LogicalDirection.Backward).GetCharacterRect(LogicalDirection.Backward); |
||||
|
|
||||
|
double left = wordBoundary.X; |
||||
|
double top = (wordBoundary.Y + wordBoundary.Height) - adorningEditor.ActualHeight; |
||||
|
|
||||
|
//top boundary
|
||||
|
if (top < 0) |
||||
|
{ |
||||
|
top = wordBoundary.Y + wordBoundary.Height; |
||||
|
} |
||||
|
|
||||
|
//right boundary
|
||||
|
if (left + adorningEditor.ActualWidth > _richTextBox.ActualWidth - 20) |
||||
|
{ |
||||
|
left = left - adorningEditor.ActualWidth; |
||||
|
top = wordBoundary.Y + wordBoundary.Height + 5; |
||||
|
} |
||||
|
|
||||
|
//bottom boundary
|
||||
|
if (top + adorningEditor.ActualHeight > _richTextBox.ActualHeight - 20) |
||||
|
{ |
||||
|
top = wordBoundary.Y - (adorningEditor.ActualHeight + wordBoundary.Height); |
||||
|
} |
||||
|
|
||||
|
_adorner.SetOffsets(left, top); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Ensures that the IRichTextFormatBar is in the adorner layer.
|
||||
|
/// </summary>
|
||||
|
/// <returns>True if the IRichTextFormatBar is in the adorner layer, else false.</returns>
|
||||
|
bool VerifyAdornerLayer() |
||||
|
{ |
||||
|
if (_adorner.Parent != null) |
||||
|
return true; |
||||
|
|
||||
|
AdornerLayer layer = AdornerLayer.GetAdornerLayer(_richTextBox); |
||||
|
if (layer == null) |
||||
|
return false; |
||||
|
|
||||
|
layer.Add(_adorner); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Hides the IRichTextFormatBar that is in the adornor layer.
|
||||
|
/// </summary>
|
||||
|
void HideAdorner() |
||||
|
{ |
||||
|
if (AdornerIsVisible) |
||||
|
{ |
||||
|
_adorner.Visibility = Visibility.Collapsed; |
||||
|
_adorner.Child = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endregion //Methods
|
||||
|
} |
||||
|
} |
||||