views:

668

answers:

2

Before I start hacking in a really crude solution, I thought I'd see if someone could give me a little nudge in the right direction.

What I really want to do is let a user select some text in a RichTextBox, click a button, and convert that text into a custom rendered control. Convert it to a Button containing the text they had selected, for instance.

+2  A: 

You can do this with Command and CommandParameter

First, bind the button to an ICommand, like:

<Button Content="Go" Command="{Binding MyCommand}" CommandParameter="{Binding ElementName=myRichTextBox, Path=Selection}" />
<RichTextBox Name="myRichTextBox" />

Then in your ViewModel or Controller or Code-behind or wherever, you expose the ICommand as a property,and point it to a method to do the work, like...

public ICommand MyCommand
{
    get
    {
        if (_queryCommand == null)
        {
            _queryCommand = new RelayCommand<TextSelection>(DoWork);
        }
        return _queryCommand;
    }
}

private void DoWork(TextSelection param)
{
    string selectedText = param.Text;

    // Build your control here...
    // probably put it in an ObservableCollection<Control> which is bound by an Items Control, like a ListBox
}

Note: I have used the RelayCommand from Josh Smith's excellent MVVM Foundation, but you could equally use a RoutedUICommand for example (which would add the extra benefit of letting you associate input gestures to your command)

IanR
Sorry, as an addition... I just tried and failed to bind to the Selection.Path of the RTB control, but if I set Path=Selection, and make my RelayCommand of type System.Windows.Documents.TextSelection (and make my handler take a parameter of the same type) it works fine...I'll update the code above to show you what I mean :)
IanR
A: 

You'll need to write some code that takes your selection and wraps it in an InlineUIContainer - that's how you get controls inside a rich text box:

<RichTextBox>
    <FlowDocument>
        <Paragraph>
            <Run>Fo</Run>
            <InlineUIContainer>
                <Button IsEnabled="True">oB</Button>
            </InlineUIContainer>
            <Run>ar</Run>
        </Paragraph>
    </FlowDocument>
</RichTextBox>
Rob Fonseca-Ensor
Hey Rob :) Huh.. it never occurred to me he might want the control actually *in* the RichTextBox... nice answer :)
IanR
I guess I wasn't clear enough on my question. This is obviously trivial in XAML, but my question was how to programatically go from the the user selecting 'oB' when there's just one <Run> containing "FooBar", to the resulting document you've shown here.
@IanR thanks, very useful!
msfanboy