わかりました、CodeNaked の回答が正しい理由を人々に示すためにこれに回答していますが、必要に応じてアスタリスクを付け、回避策を提供します。しかし、良いSO市民権では、彼の回答が私をここに導いたので、私はまだ彼を回答済みとしてマークしています。
更新:2つの理由から、受け入れられた回答をここに移動しました。1つは、これに対する解決策があることを人々に知ってもらいたい(ほとんどの人は、受け入れられた回答を読んで先に進むだけです). ! :)
これが私がしたことです。これをテストするために、このサブクラスを作成しました...
public class TestPanel : DockPanel
{
protected override Size MeasureOverride(Size constraint)
{
System.Console.WriteLine("MeasureOverride called for " + this.Name + ".");
return base.MeasureOverride(constraint);
}
protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
{
System.Console.WriteLine("ArrangeOverride called for " + this.Name + ".");
return base.ArrangeOverride(arrangeSize);
}
protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
System.Console.WriteLine("OnRender called for " + this.Name + ".");
base.OnRender(dc);
}
}
...私はこのようにレイアウトしました(ネストされていることに注意してください):
<l:TestPanel x:Name="MainTestPanel" Background="Yellow">
<Button Content="Test" Click="Button_Click" DockPanel.Dock="Top" HorizontalAlignment="Left" />
<l:TestPanel x:Name="InnerPanel" Background="Red" Margin="16" />
</l:TestPanel>
ウィンドウのサイズを変更すると、これが得られました...
MeasureOverride called for MainTestPanel.
MeasureOverride called for InnerPanel.
ArrangeOverride called for MainTestPanel.
ArrangeOverride called for InnerPanel.
OnRender called for InnerPanel.
OnRender called for MainTestPanel.
しかし、InvalidateVisual
(ボタンの「Click」イベントで)「MainTestPanel」を呼び出すと、代わりにこれが得られました...
ArrangeOverride called for MainTestPanel.
OnRender called for MainTestPanel.
測定オーバーライドが呼び出されず、外側のコントロールの ArrangeOverride のみが呼び出されたことに注意してください。
サブクラスの内部に非常に重い計算がありArrangeOverride
(残念ながらそうです)、まだ (再) 実行されているかのように完璧ではありませんが、少なくとも子供たちは同じ運命に陥ることはありません。
ただし、どの子コントロールにも AffectsParentArrange ビットが設定されたプロパティがないことがわかっている場合は (これも行います)、さらに良い方法で NullableSize
をフラグとして使用して、ArrangeOverride ロジックが必要な場合を除いて再入力されないようにすることができます。 、 そのようです...
public class TestPanel : DockPanel
{
Size? arrangeResult;
protected override Size MeasureOverride(Size constraint)
{
arrangeResult = null;
System.Console.WriteLine("MeasureOverride called for " + this.Name + ".");
return base.MeasureOverride(constraint);
}
protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
{
if(!arrangeResult.HasValue)
{
System.Console.WriteLine("ArrangeOverride called for " + this.Name + ".");
// Do your arrange work here
arrangeResult = base.ArrangeOverride(arrangeSize);
}
return arrangeResult.Value;
}
protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
System.Console.WriteLine("OnRender called for " + this.Name + ".");
base.OnRender(dc);
}
}
これで、(MeasureOverride の呼び出しのように) 特にアレンジ ロジックを再実行する必要がない限り、OnRender のみが取得されます。アレンジ ロジックを明示的に強制したい場合は、単にサイズを null にして、InvalidateVisual を呼び出して、ボブの叔父さんを呼び出してください! :)
お役に立てれば!