如何折叠段落?

时间:2010-09-26 14:40:47

标签: .net wpf flowdocument paragraph

如何在保持文本可选的同时使段落在FlowDocument中可折叠?

1 个答案:

答案 0 :(得分:1)

这必须是有史以来最丑陋的扩展之一(就代码视觉效果而言),但它“使Paragraph可以抓取”并且文本仍然可以选择。

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 使段落可折叠可能不是最好的方法,我认为这种功能相当于面板/包络文档应该处理的事情。