在基本窗口类中包装窗口内容

时间:2013-05-01 07:35:01

标签: wpf

在具有从基类继承的多个窗口的应用程序 - BaseWindow中,我想在每个窗口上都有一个状态栏。我假设这必须用代码完成,因为一个XAML生成的类不能从另一个继承。

XAML看起来像这样:

<my:BaseWindow x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:WpfApplication1">
    <StackPanel>
        <TextBlock Text="Content" />
    </StackPanel>
</my:BaseWindow>

和BaseWindow类:

public class BaseWindow : Window {
    protected override void OnContentChanged(object oldContent, object newContent) {
        var sb = new StatusBar();
        sb.Items.Add(new TextBlock {
            Text = "Status bar"
        });

        var dp = new DockPanel();
        dp.Children.Add(sb);
        DockPanel.SetDock(sb, Dock.Bottom);
        dp.Children.Add((UIElement)newContent);

        base.OnContentChanged(oldContent, dp);
    }
}

引发以下错误:在附加到新的父Visual之前,必须断开指定子项与当前父Visual的连接。

我该如何解决这个问题?或者,我可以用什么其他技术来实现这个目标?

2 个答案:

答案 0 :(得分:2)

您可以将其作为“子”窗口的容器,而不是从基本窗口继承,例如通过制作Pages并将它们放入基本窗口内的Frame中,或者将它们设置为UserControls并使用DataTemplates以便在不同的窗口之间切换。

你也可以使用ContentPresenter使你的BaseWindow成为UserControl,而不是从它继承,你可以将它作为你窗口的第一个内容元素,并把它们需要显示的任何内容放在里面。

答案 1 :(得分:1)

设置Content而不是调用base.OnContentChanged有效:

Content = dp;

但是,直接设置Content将调用OnContentChanged,从而导致无限循环。对于我此时的需求,一个简单的标志就足够了:

private bool firstRun = true;
protected override void OnContentChanged(object oldContent, object newContent) {
    if (!firstRun) { return; }

    ...

    firstRun = false;
    Content = dp;
}