我试图从System.Windows.Controls.TabItem班级继承MyTabItem
。问题是,原始TabItem
具有通用object
类型的属性:
public object Header;
public object Content;
我试图在不同类型的派生类中隐藏这些属性。
public class MyTabItem: TabItem
{
public new MyTabHeader Header;
public new MyTabContent Content;
}
这样,我可以在不进行类型转换的情况下访问MyTabItem.Header
和MyTabItem.Content
。
这个想法相当不错,代码编译正确。但是,当应用程序启动时,我看到空控件(没有报告错误)。当我删除这些行并使用基类属性时,它可以正常工作。
当然,我可以添加两个额外的属性,这些属性会在内部返回已投放的(MyTabHeader)Header
或(MyTabContent)Header
,但这似乎有点多余。
我问是否有其他方法可以正确实现这些属性,因此它们实际上可以在我的应用程序中使用。
答案 0 :(得分:4)
这完全违背了WPF的设计方式。您的XAML对象应该与数据松散绑定,在绝大多数情况下,您甚至不需要创建自定义控件。您正在这样做,然后尝试用您自己的类型安全版本替换成员,这意味着您的视图代码和视图逻辑代码不再分离,这将使您感到头疼赛道。
如果您需要动态标签,那么一种方法是首先声明一个表示您的页面的抽象类,并从中派生您的页面类型:
public interface IBasePage
{
string Header { get; }
}
public class MyPageA : ViewModelBase, IBasePage
{
public string Header { get { return "Page A"; } }
}
public class MyPageB : ViewModelBase, IBasePage
{
public string Header { get {return "Page B";} }
}
public class MyPageC : ViewModelBase, IBasePage
{
public string Header { get {return "Page C";} }
}
您的视图模型(应该将您的窗口DataContext设置为)应该包含您希望显示的选项卡式页面的集合:
public class MyViewModel : ViewModelBase
{
private IEnumerable<IBasePage> _MyPages = new List<IBasePage>(){
new MyPageA(),
new MyPageB(),
new MyPageC()
};
public IEnumerable<IBasePage> MyPages {get {return this._MyPages;}}
}
然后,XAML中的选项卡控件与此松散绑定,并且应该包含TabItem的样式(因此它知道要用于标题的文本等)和DataTemplates,以便它知道如何呈现每种页面类型你创造了:
<TabControl ItemsSource="{Binding MyPages}" SelectedItem="{Binding MyPages[0], Mode=OneTime}">
<TabControl.Resources>
<!-- TabItem style -->
<Style TargetType="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Header}" />
</Style>
<!-- Content templates -->
<DataTemplate DataType="{x:Type local:MyPageA}">
<TextBlock Text="This is page A" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:MyPageB}">
<TextBlock Text="This is page B" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:MyPageC}">
<TextBlock Text="This is page C" />
</DataTemplate>
</TabControl.Resources>
</TabControl>
最终结果是一个完全由数据驱动的常规选项卡控件,并且绑定到已经强类型的模型: