Silverlight DataBinding,避免丢失属性上的BindingExpression Path错误,而是隐藏控件

时间:2010-07-22 14:33:28

标签: silverlight data-binding silverlight-4.0

想象一下以下简单的模型(出于简单原因的例子;实际上,我们这里有MVVM,但没关系):

public class User {
  public string Username { get; set; }
}

public class StackOverflowUser : User {
  public int Reputation { get; set; }
}

现在我们有一个Silverlight UserControl,其中包含以下Controls(再次,这只是一个示例,剥离到核心):

<Grid>
    <TextBlock Text="Username:" />
    <TextBlock Text="{Binding Path=Username}" />

    <TextBlock Text="Reputation:" />
    <TextBlock Text="{Binding Path=Reputation}" />
</Grid>

现在我希望此UserControl与这两个模型UserStackOverflowUser兼容。我可以将UserControl的DataContext设置为UserStackOverflowUser类型:

this.DataContext = new User { Username = "john.doe" };

如果设置为StackOverflowUser,一切正常。如果设置为User,则会收到“BindingExpression Path错误”,因为Reputation模型中缺少属性User。我完全理解。

  

有没有办法1)避免这种情况   例外和2)控制   崩溃的可见性   当绑定属性不可用时?

当然,我们更喜欢优雅的解决方案,通过调整绑定表达式和/或使用转换器等解决问题,并尽可能避免大量代码。

提前感谢您的帮助和建议,
最好的问候,

托马斯

4 个答案:

答案 0 :(得分:1)

不幸的是,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}">

您也可以尝试(我无法测试):

  1. 为User类提供一个标识其类型的新属性
  2. 为第二个TextBlock创建第二个Style
  3. 将其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>
    
  4. 但是你看,没有优雅的方式,遗憾的是DataTemplate在Silverlight中没有DataType属性。

答案 1 :(得分:1)

答案 2 :(得分:0)

我终于解决了我的问题。一位同事最终实现了一个解决方案,其中包括WPF DataTemplates DataType属性(或通常是DataTemplateSelector)的解决方法。它不是很漂亮(我猜,没有解决办法)但它的确有效。不幸的是,我不能发布任何代码片段,因为它是封闭源代码。但我之后发现了一些链接,提供了一个非常类似的解决方案,如下所示:Silverlight: a port of the DataTemplateSelector。如果您遇到类似问题,这也会对您有所帮助。 Herethere对此主题有更多的想法。

实际的解决方案是遵循Ozan的提示。不幸的是,他的解决方案不起作用,所以我不想将他的评论标记为已接受的答案,但我至少给了一个upvote。

谢谢!

最好的问候,

托马斯

答案 3 :(得分:0)

我知道这已经得到了解答,但我仍然认为它值得这篇文章。使用反射,您可以在ViewModel中拥有一个属性,该属性可以轻松处理有时只具有该属性的Dto对象。反思可能很昂贵,所以要根据你的决定权衡。

public int? Reputation
    {
        get
        {
            var prop = Dto.GetType().GetProperty("Reputation");
            return (prop != null)? (int)prop.GetValue(Dto, null) : null;
        }
        set
        {
            var prop = Dto.GetType().GetProperty("Reputation");
            if(prop !=null) prop.SetValue(Dto,value, null);
        }
    }