我试图在WPF Window
s上模拟ASP.Net主页概念(MVC中的布局)。
我有一个CustomWindow
类,为这类Window
s指定了一些行为:
public class CustomWindow : Window
{
//...
}
MasterWindowBase
;一个CustomWindow
,它将某种UserControl
作为窗口内容(通过样式):
public abstract class MasterWindowBase : CustomWindow
{
public MasterWindowBase(MyUserControlBase content)
{
ContentUserControl = content;
Style = Application.Current.FindResource("MasterWindowStyle") as Style;
}
#region ContentUserControl Property
public MyUserControlBase ContentUserControl
{
get { return (MyUserControlBase)GetValue(ContentUserControlProperty); }
set { SetValue(ContentUserControlProperty, value); }
}
public static readonly DependencyProperty ContentUserControlProperty =
DependencyProperty.Register("ContentUserControl", typeof(MyUserControlBase), typeof(MasterWindowBase));
#endregion
}
应用程序资源中定义的样式:
<Style x:Key="MasterWindowStyle" TargetType="{x:Type local:MasterWindowBase}">
<Setter Property="Content">
<Setter.Value>
<Grid>
<StackPanel>
<TextBlock Text="This is a master window"/>
<ContentPresenter Content="{Binding ContentUserControl, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MasterWindowBase}}}"/>
</StackPanel>
</Grid>
</Setter.Value>
</Setter>
</Style>
MasterWindow
;用于创建具有指定MasterWindowBase
类型的UserControl
实例的通用窗口:
public class MasterWindow<TMyUserControlBase>
: MasterWindowBase
where TMyUserControlBase : MyUserControlBase, new()
{
public MasterWindow() : base(new TMyUserControlBase()) { }
}
现在第一个Window.Show
,一切都很完美,但后来我发现了两个逻辑错误:
UserControl
显示其新实例时,它会加载第一个显示MasterWindow
的内容。MasterWindow
的新实例时,使用相同的UserControl
或使用不同的实例而不关闭当前显示的窗口,它会清除当前显示的所有内容MasterWindow
个实例,并在新实例中加载首先显示的MasterWindow
的内容。 请注意,我无法在Template
样式中使用MasterWindowStyle
属性,因为该样式实际上基于CustomWindow
的样式(在已经使用Template
属性的实际项目。
任何帮助将不胜感激。
答案 0 :(得分:1)
观察到的行为的原因是您尝试在Style中设置窗口的内容。因为它不是模板 - WPF只会使用UserControl创建一次树。然后,当您反复应用此样式时 - 每次都重复使用相同的可视树(具有相同的,第一个,UserControl)(当然,一个控件不能在不同的父项中使用 - 因此它将从现在托管的位置删除并移动到您应用样式的窗口)。
长话短说 - 你不应该在WPF中通过Style设置内容。要解决您的紧急问题,您只需设置 ContentTemplate 属性而不是Content,并将您在DataTemplate中的内容包装起来(其他所有内容都相同)。这将解决它,因为对于模板,每次都会创建新的可视化树。
这是修复它的另一种方法,仍然使用Content属性,但它看起来像是一种黑客攻击而且我最好无效(尽管仍然有效):
<Application.Resources>
<Grid x:Shared="False" x:Key="myControl">
<StackPanel>
<TextBlock Text="This is a master window"/>
<ContentPresenter Content="{Binding ContentUserControl, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MasterWindowBase}}}"/>
</StackPanel>
</Grid>
<Style x:Key="MasterWindowStyle" TargetType="{x:Type local:MasterWindowBase}">
<Setter Property="Content">
<Setter.Value>
<StaticResource ResourceKey="myControl" />
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
在这里,您可以使用x:Shared =&#34; False&#34;在资源中定义可视树。属性。此属性表示每次引用此资源时 - 将创建新实例(默认情况下 - 重用相同的实例)。然后在Style中引用此资源。