.net 如何折叠段落?

.net 如何折叠段落?,.net,wpf,flowdocument,paragraph,.net,Wpf,Flowdocument,Paragraph,如何在保持文本可选性的同时使段落在FlowDocument中可折叠?这必须是有史以来最丑陋的扩展之一(在代码和视觉方面),但它“使段落可协作”,并且文本仍然是可选的 public static class ParagraphExtensions { private static Dictionary<Paragraph, InlineUIContainer> _collapseButtonDictionary; private static Dictionary<

如何在保持文本可选性的同时使段落在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();
        }
    }
}
公共静态类段落扩展
{
私有静态字典(collapseButtonDictionary);;
专用静态字典_段线性存储;
公共静态只读从属属性IsCollappibleProperty=
DependencyProperty.RegisterAttached(“IsCollapsible”、typeof(bool)、typeof(段落)、新UIPropertyMetadata(false、IsCollapsibleChanged));
公共静态bool GetIsCollapsible(DependencyObject obj)
{
返回(bool)对象GetValue(IsCollapsibleProperty);
}
公共静态void SetIsCollapsible(DependencyObject对象,布尔值)
{
对象设置值(IsCollapsibleProperty,value);
}
私有静态void IsCollapsibleChanged(对象发送方,DependencyPropertyChangedEventArgs e)
{
如果(_collapseButtonDictionary==null)_collapseButtonDictionary=newdictionary();
如果(_paragraphInlineStorage==null)_paragraphInlineStorage=new Dictionary();
第p段=发送方作为第3段;
if((bool)e.NewValue)
{
内联集装箱;
if(_collapseButtonDictionary.ContainsKey(p))
{
容器=_collapseButtonDictionary[p];
}
其他的
{
ToggleButton=newtogglebutton(){Tag=p,Content=“Hide”};
container=newinlineuicontainer(){Child=button};
_collapseButtonDictionary.Add(p,容器);
按钮。单击+=新建路由EventHandler(折叠按钮单击);
}
如果(p.Inlines.Count>0)
{
p、 InsertBefore(p.Inlines.First(),容器);
}
其他的
{
p、 Inlines.Add(容器);
}
}
其他的
{
if(_collapseButtonDictionary.ContainsKey(p))
{
var容器=_collapseButtonDictionary[p];
var tb=container.Child作为ToggleButton;
如果((bool)tb.IsChecked)设置CollapsedState(false,p);
p、 内联线。移除(容器);
_折叠式按钮缩略。移除(p);
}
}
}
专用静态空白折叠按钮单击(对象发送器,路由目标e)
{
ToggleButton=发送方为ToggleButton;
var p=按钮。标记为段落;
SetCollapsedState((bool)button.IsChecked,p);
}
私有静态void SetCollapsedState(bool isCollapsed,第p段)
{
InlineUIContainer buttonContainer=_collapseButtonDictionary[p];
列出不可禁用的数据线;
如果(_段落linestorage.ContainsKey(p))
{
DisabledLines=_段落线性存储[p];
}
其他的
{
disabledInlines=新列表();
_段落linestorage.Add(p,disabledInlines);
}
如果(已合并)
{
foreach(p.Inlines中的变量项)
{
禁用dinlines。添加(项);
}
p、 Inlines.Clear();
p、 添加(按钮容器);
}
其他的
{
p、 Inlines.Clear();
foreach(不允许的行中的var项)
{
p、 内联线。添加(项目);
}
禁用dinlines.Clear();
}
}
}
Lorem Ipsum

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

我想知道这是否仍然与您相关,但要回答这个问题,我必须问:如何选择要折叠的段落中的文本?(重新措辞:折叠段落=>无文本=>选择什么?)
<Paragraph local:ParagraphExtensions.IsCollapsible="True">Lorem Ipsum</Paragraph>