想象下面的简单模型(例子为了简单起见;实际上,我们这里有MVVM,但没关系):
public class User {
public string Username { get; set; }
}
public class StackOverflowUser : User {
public int Reputation { get; set; }
}
现在我们有一个Silverlight UserControl,它包含以下控件(同样,这只是一个示例,剥离到核心):
<Grid>
<TextBlock Text="Username:" />
<TextBlock Text="{Binding Path=Username}" />
<TextBlock Text="Reputation:" />
<TextBlock Text="{Binding Path=Reputation}" />
</Grid>
现在我希望这个UserControl与Models,User和StackOverflowUser兼容.我可能会将UserControl的DataContext设置为User或StackOverflowUser类型:
this.DataContext = new User { Username = "john.doe" };
如果设置为StackOverflowUser,一切正常.如果设置为User,我收到“BindingExpression Path错误”,因为用户模型中缺少属性信誉.我完全理解.
Is there any way to 1) avoid this
exception and 2) control the
visibility of the controls, collapse
when bound property is not available?
当然,我们更喜欢优雅的解决方案,通过调整绑定表达式和/或使用转换器等解决问题,并尽可能避免大量代码.
提前感谢您的帮助和建议,
最好的祝福,
托马斯
最佳答案 不幸的是,Silverlight在DataTemplates方面的多态行为有限,我只能想到一个解决方法:
为User类提供属性声誉,但使其无意义,例如-1.然后将样式应用于声誉TextBlocks:
<Page.Resources>
<Style Key="Reputation">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Reputation} Value="-1">
<Setter Property="Visibility" Value="Invisible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Page.Resources>
...
<TextBlock Text="Reputation:" Style="{StaticResource Reputation}">
<TextBlock Text="{Binding Path=Reputation}" Style="{StaticResource Reputation}">
你也可以尝试(我无法测试):
>为User类提供一个标识其类型的新属性,
>为第二个TextBlock创建第二个Style
>将其DataTrigger绑定到类型标识属性,并将{Binding Path = Reputation}声明移动到Setter中:
<Style Key="ReputationContent">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Type} Value="StackOverflow">
<Setter Property="Visibility" Value="Invisible" />
<Setter Property="Text" Value="{Binding Path=Reputation}" />
</DataTrigger>
</Style.Triggers>
</Style>
但是你看,没有优雅的方式,遗憾的是DataTemplate在Silverlight中没有DataType属性.