【问题标题】:ArrangeOverride calls arranging children before calling more codeArrangeOverride 在调用更多代码之前调用安排子项
【发布时间】:2011-02-03 15:54:11
【问题描述】:

好吧,就在我以为我已经弄清楚了布局系统的时候,我碰了壁……

所以我有一个带有自定义 ItemsControl 的 WPF 窗口,其中的 Items 面板是一个自定义 Panel,每个 ItemContainer 都是一个自定义元素。

当窗口调用 InvalidateArrange() 时,ArrangeOverride() 调用的顺序似乎很好,即

Window -> List -> ItemsPanel -> ItemContainer -> ItemContainer -> etc...

问题是,我想在依赖于所有已排列和调整大小的 ItemContainers 的 ArrangeOverride 之后在窗口级别调用一些代码。窗口级别 ArrangeOverride() 在树(列表)中的下一个项目调用 ArrangeOverride 之前结束。

有没有办法测量所有的 windows 子项,然后返回到 Windows ArrangeOverride() 以继续执行某些代码,或者是否有要挂钩的事件之类的?

干杯

【问题讨论】:

    标签: c# wpf layout


    【解决方案1】:

    您可以在窗口的 ArrangeOverride 实现中调用 base.ArrangeOverride() 之后调用您的自定义代码:

        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            Size temp = base.ArrangeOverride(arrangeBounds);
    
            // custom code goes here!
    
            return temp;
        }
    

    (我刚刚测试过,可以正常运行:自定义代码在窗口中任意子控件的ArrangeOverride之后执行)

    编辑: 遵循一个经过测试和工作的示例:

    在window1.xaml.cs中:

    [...]
    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        Trace.TraceInformation("Window1.ArrangeOverride START");
        Size temp = base.ArrangeOverride(arrangeBounds);
        Trace.TraceInformation("Window1.ArrangeOverride END");
        return temp;
    }
    [...]
    

    在 myUserControl.xaml.cs 中:

    [...]
    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        Trace.TraceInformation("{0}.ArrangeOverride START", Tag);
        Size s = base.ArrangeOverride(arrangeBounds);
        Trace.TraceInformation("{0}.ArrangeOverride END", Tag);
        return s;
    }
    [...]
    

    在window1.xaml中:

    [...]
    <local:myUserControl Tag="FirstLevelControl">
        <StackPanel>
            <local:myUserControl Tag="SecondLevelControl_1">
                <TextBlock>First</TextBlock>
            </local:myUserControl>
            <local:myUserControl Tag="SecondLevelControl_2">
                <TextBlock>Second</TextBlock>
            </local:myUserControl>
        </StackPanel>
    </local:myUserControl>
    [...]
    

    最后是执行后的输出:

    [...]
    Test.vshost.exe Information: 0 : Window1.ArrangeOverride START
    Test.vshost.exe Information: 0 : FirstLevelControl.ArrangeOverride START
    Test.vshost.exe Information: 0 : SecondLevelControl_1.ArrangeOverride START
    Test.vshost.exe Information: 0 : SecondLevelControl_1.ArrangeOverride END
    Test.vshost.exe Information: 0 : SecondLevelControl_2.ArrangeOverride START
    Test.vshost.exe Information: 0 : SecondLevelControl_2.ArrangeOverride END
    Test.vshost.exe Information: 0 : FirstLevelControl.ArrangeOverride END
    Test.vshost.exe Information: 0 : Window1.ArrangeOverride END
    [...]
    

    这表明temp = base.ArrangeOverridereturn temp 之间的代码行总是在所有嵌套用户控件的ArrangeOverride 方法中的所有代码之后执行。我没有尝试跟踪内置控件的排列的执行,但我想它们具有相同的行为。

    【讨论】:

    • 当然,这不是 ArrangeOverride 方法的通用实现,任何额外的逻辑都可以在调用 base.ArrangeOverride 之前发生。这个例子只是为了展示在所有内容的 ArrangeOverride 方法被执行后将执行的放置代码。
    • 嗯,那我的代码一定有些奇怪。如果我在 base.ArrangeOverride 调用上断点,子对象 ArrangeOverride 和父对象中的返回 temp,则父对象 ArrangeOverride 函数在子对象到达其 ArrangeOverride 之前返回。
    • @Xeno:我添加了更详细的示例,并带有输出结果。如果您仍然发现问题,请告诉我! ;)
    • 好的,您的解决方案在给出的示例中确实有效,但我的代码似乎没有,我想我知道为什么。检查 WPF 属性时,没有一个 ItemContainers 有父级(位于 null),ItemsPanel 也没有。列表知道窗口是父窗口,但其他人都不知道。知道为什么通过自定义 ItemsPanel 添加到 ItemsControl 的项目没有父项吗?
    • @Xeno:我认为这是另一个问题。无论如何,如果您发布一些代码摘录会更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 2016-11-12
    • 1970-01-01
    相关资源
    最近更新 更多