Link to home
Start Free TrialLog in
Avatar of gem56
gem56

asked on

Get selected table cells in WPF RichTextBox

hi guys,

i have a table in a wpf rtb control, im trying to build a solution for merging table cells. at the moment my algorithm can determine the correct row and column spans, however im getting stuck when it comes time to delete the required cells.

initially my code worked flawlessly across column merging, however when row merging came into the picture i cant seem to find my way out. the problem was dealing with varying row spans and deleting the right cells under the right conditions, however i find that there seems to be multiple variations to have to deal with with this method. i figured the easier solution would be to collect all the cells within my RTB.Selection and and simply .Parent, .IndexOf, .Remove, etc. now my last problem is my weakness with TextPointers and trying to wrap my head around the new WPF RTB control...hence, does anyone have a solution for being able to find the TableCells within my Selection() ?

cheers
Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

I would suggest you to use the Request Attention button and ask moderators to add the "WPF and Silverlight" zone to your question.
Avatar of gem56
gem56

ASKER

done, cheers mate.
How are you building the content for the RichTextBox?  The usual assumption is a FlowDocument...
Avatar of gem56

ASKER

Hello TheLearnedOne,

yes the content is contained within a flow document.
Here is a little LINQ magic, that I came up with, but I haven't had a chance to test:


        public static List<Paragraph> GetSelectedParagraphs(FlowDocument document, TextSelection selection)
        {
            return document.Blocks.OfType<Paragraph>().Where(w => selection.Contains(w.ContentStart)).ToList();
        }
Avatar of gem56

ASKER

hello again TheLearnedOne, thanks for the reply.

i've just converted your code to the vb equivalent, however unfortunately either the conversion isnt correct...or somethings not working in the function. basically i just keep getting an empty list returned.

    Public Function GetSelectedCells(ByVal selection As TextSelection) As List(Of TableCell)
        Return flowDoc.Blocks.OfType(Of TableCell)().Where(Function(w) selection.Contains(w.ContentStart)).ToList()
    End Function

Open in new window


any ideas?
cheers
I would suggest breaking that down, and see what is failing:

1) Dim cellList As List(Of TableCell) = flowDoc.Blocks.OfType(Of TableCell).ToList()

2) Dim selectedCellList As List(Of TableCell) = cellList.Where(Function(w) selection.Contains(w.ContentStart)).ToList()
Avatar of gem56

ASKER

ok so i've done a little learning and playing around with these lambda functions and OfType/Where methods. seems that the OfType method will only filter through the immediate children of the calling object. makes sense.

sorry for not stating it earlier, the format of my flow document is as follows: flowDoc -> 1 block -> 1 table -> 1 row group -> multiple rows -> multiple cells.

since im trying to cater for multiple cells selected over multiple rows..and the OfType method only looks at the immediate children, i've had to go the for each path as follows:

    Public Function GetSelectedCells(ByVal selection As TextSelection) As List(Of TableCell)

        Dim cells As List(Of TableCell) = New List(Of TableCell)

        For Each tblRow In rtbTable.RowGroups(0).Rows     ' where rtbTable = CType(flowDoc.Blocks(0), Table)
            cells.AddRange(tblRow.Cells.OfType(Of TableCell)().Where(Function(w) selection.Contains(w.ContentStart)).ToList)
        Next

        Return cells

    End Function

Open in new window


im calling the method with richtextbox.Selection (as i assume you'd be expecting) and although im getting results now, im getting inaccurate results.

lets say my flow document is made up of a 5 x 5 table, my selection is 2 cells (row 1 cell 1 and row 2 cell 1). my GetSelectedCells function is returning 3 cells (row 1 cell 1, row 1 cell 2, row 2 cell 2). not sure why, im guessing theres some confusion or inaccuracy in the .Selection text pointer being in the wrong position.

any thoughts? also is there maybe a more elegant way of doing this? is it possible of converting this function to use generics(instead of TableCell's) given the hierarchy of the cells/rows/table etc?

cheers
ASKER CERTIFIED SOLUTION
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gem56

ASKER

hmm..

interestingly enough i initially started with something like that in the first place, however it didnt seem to work as 'selection.Contains(x)' was still getting triggered for cells in between the selected cells from a left-to-right logical view.

i've changed 'w.ContentStart' to 'cell.ConrtentEnd' as 'w' is not longer infered by the compiler and the ContentStart pointer position causes inaccuracies due to the opening tags and next insertion position.

either way the solution works great, many thanks TheLearnedOne :)