.net - 如何折叠段落?

标签 .net wpf flowdocument paragraph

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

最佳答案

这一定是有史以来最丑陋的扩展之一(就代码视觉效果而言),但它“使段落可折叠”并且文本仍然可选。

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>

实际上使段落可折叠可能不是最好的方法,我认为这种功能应该由面板/信封文档来处理。

关于.net - 如何折叠段落?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3798262/

相关文章:

c# - WPF:richtextbox 选项卡问题

c# - 使用List.Sort()时忽略空白

c# - 在 WPF/C# 中嵌入 Firefox/Gecko

c# - 查询 Active Directory 的任务并行库(使用 DirectoryServices)

c# - 向 Scrollviewer 内容添加不透明蒙版,而不影响滚动条本身

WPF自定义进度条剪辑

c# - WPF - FlowDocument 的自动行号?

.net - WPF 中的文档布局有哪些选项?

c# - 如何将 Ninject 配置为始终停用池化引用?

c# - 如何为 Binary Formatter 创建一个 SerializationBinder 来处理类型从一个程序集和命名空间到另一个的移动