开发者

How to collapse a paragraph?

How can I make a Paragra开发者_开发百科ph collapsible in a FlowDocument while keeping its text selectable?


This has to be one of the ugliest extensions ever (in terms of code and visuals) but it "makes a Paragraph collabsible" and the text is still selectable.

public static class ParagraphExtensions
{
    private static Dictionary<Paragraph, InlineUIContainer> _collapseButtonDictionary;
    private static Dictionary<Paragraph, List<Inline>> _paragraphInlineStorage;

    public static readonly DependencyProperty IsCollapsibleProperty =
        DependencyProperty.RegisterAttached("IsCollapsible", typeof(bool), typeof(Paragraph), new UIPropertyMetadata(false, IsCollapsibleChanged));
    public static bool GetIsCollapsible(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsCollapsibleProperty);
    }
    public static void SetIsCollapsible(DependencyObject obj, bool value)
    {
        obj.SetValue(IsCollapsibleProperty, value);
    }

    private static void IsCollapsibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if (_collapseButtonDictionary == null) _collapseButtonDictionary = new Dictionary<Paragraph, InlineUIContainer>();
        if (_paragraphInlineStorage == null) _paragraphInlineStorage = new Dictionary<Paragraph, List<Inline>>();

        Paragraph p = sender as Paragraph;
        if ((bool)e.NewValue)
        {

            InlineUIContainer container;
            if (_collapseButtonDictionary.ContainsKey(p))
            {
                container = _collapseButtonDictionary[p];
            }
            else
            {
                ToggleButton button = new ToggleButton() { Tag = p, Content = "Hide" };
                container = new InlineUIContainer() { Child = button };
                _collapseButtonDictionary.Add(p, container);
                button.Click += new RoutedEventHandler(CollapseButton_Click);
            }
            if (p.Inlines.Count > 0)
            {
                p.Inlines.InsertBefore(p.Inlines.First(), container);
            }
            else
            {
                p.Inlines.Add(container);
            }
        }
        else
        {
            if (_collapseButtonDictionary.ContainsKey(p))
            {
                var container = _collapseButtonDictionary[p];
                var tb = container.Child as ToggleButton;
                if ((bool)tb.IsChecked) SetCollapsedState(false, p);
                p.Inlines.Remove(container);
                _collapseButtonDictionary.Remove(p);
            }
        }
    }

    private static void CollapseButton_Click(object sender, RoutedEventArgs e)
    {
        ToggleButton button = sender as ToggleButton;
        var p = button.Tag as Paragraph;
        SetCollapsedState((bool)button.IsChecked, p);
    }

    private static void SetCollapsedState(bool isCollapsed, Paragraph p)
    {
        InlineUIContainer buttonContainer = _collapseButtonDictionary[p];
        List<Inline> disabledInlines;
        if (_paragraphInlineStorage.ContainsKey(p))
        {
            disabledInlines = _paragraphInlineStorage[p];
        }
        else
        {
            disabledInlines = new List<Inline>();
            _paragraphInlineStorage.Add(p, disabledInlines);
        }
        if (isCollapsed)
        {
            foreach (var item in p.Inlines)
            {
                disabledInlines.Add(item);
            }
            p.Inlines.Clear();
            p.Inlines.Add(buttonContainer);
        }
        else
        {
            p.Inlines.Clear();
            foreach (var item in disabledInlines)
            {
                p.Inlines.Add(item);
            }
            disabledInlines.Clear();
        }
    }
}
<Paragraph local:ParagraphExtensions.IsCollapsible="True">Lorem Ipsum</Paragraph>

Litterally making the paragraph collapsible is probably not the best approach, i think this kind of functionality is rather something the panel/enveloping document should take care of.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜