2008-12-15 105 views
2

让我们假设我有以下XAML ...Silverlight的数据绑定 - 绑定ValueConverter一个属性上的视图模型

<UserControl.Resources> 
    <local:ViewModel x:Name="viewModel" /> 
    <local:LoadChildrenValueConverter x:Name="valueConverter" /> 
</UserControl.Resources> 

<UserControl.DataContext> 
    <Binding Source="{StaticResource viewModel}" /> 
</UserControl.DataContext> 

<Grid x:Name="LayoutRoot" Background="White"> 
    <control:TreeView ItemsSource="{Binding Root}"> 
     <control:TreeView.ItemTemplate> 
      <control:HierarchicalDataTemplate ItemsSource="{Binding Converter={StaticResource valueConverter}}"> 
       <TextBlock Text="{Binding}" /> 
      </control:HierarchicalDataTemplate> 
     </control:TreeView.ItemTemplate> 
    </control:TreeView> 
</Grid> 

...和下​​面的代码去与它...

 
using System; 
using System.Collections.ObjectModel; 
using System.Windows.Data; 

namespace SilverlightViewModelSpike 
{ 
    public class ViewModel 
    { 
     public ViewModel() 
     { 
      Root = new ObservableCollection() { "Item 1", "Item 2", "Item 3", }; 
     } 

     public ObservableCollection Root { get; private set; }   
    } 

    public class LoadChildrenValueConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      return new ObservableCollection() { "Item 1", "Item 2", "Item 3", }; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

这符合预期,但它感觉不对,我有两个单独的类这是为了获取我的视图所需的数据所需的(假设ViewModel和LoadChildrenValueConverter从Web服务中提取数据而不是返回硬编码数据)。这里有更好的解决方案吗?我想也许这样的事情...

 
using System; 
using System.Collections.ObjectModel; 
using System.Windows.Data; 

namespace SilverlightViewModelSpike 
{ 
    public class ViewModel 
    { 
     public ViewModel() 
     { 
      Root = new ObservableCollection() { "Item 1", "Item 2", "Item 3", }; 
      ValueConverter = new LoadChildrenValueConverter(); 
     } 

     public ObservableCollection Root { get; private set; } 
     public LoadChildrenValueConverter ValueConverter { get; private set; } 
    } 

    public class LoadChildrenValueConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      return new ObservableCollection() { "Item 1", "Item 2", "Item 3", }; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

...但我不能让这条线的工作...

<control:HierarchicalDataTemplate ItemsSource="{???}">

...甚至认为似乎并不是一个很好的解决方案。有没有人有一个很好的干净的解决方案呢?

回答

4

由于您使用ViewModel来坐在您的实际模型和视图之间,我想知道是否更容易直接在那里实现IValueConverter逻辑。有点像:

public class ViewModel 
{ 
    public ObservableCollection Root { get; set: } 

    public ObservableCollection Children 
    { 
     get { /* return children items */ } 
    } 
} 

然后,您只需直接绑定到你的第二个属性:

<control:HierarchicalDataTemplate ItemsSource="{Binding Children}"> 

我认为一个视图模型对象的主要目的是限制的“招数”的数字(如IValueConverters),您需要从原始模型中获取所需的数据。既然你有一个,你也可以使用它。

编辑1

...当然现在我重新阅读您的文章我看到有更多的它。你在为你的“Root”系列中的每个项目收集孩子。

如何在您的ViewModel本身中实现IValueConverter作为静态实例?

public class ViewModel : IValueConverter 
{ 
    public static readonly IValueConverter ChildrenConverter 
     = new LoadChildrenValueConverter(); 
} 

现在,你应该能够说:

<control:HierarchicalDataTemplate 
    ItemsSource="{Binding Converter={x:Static local:ViewModel.ChildrenConverter}}"> 

编辑2

好吧,你使用Silverlight这样{X:静态}不是提供给您。

我可以想到的唯一的其他选项可以让您重用一个静态资源,而不必声明两个是直接在您的ViewModel中实现IValueConverter。如果您需要进行多种类型的转换,这并不好,但如果您的ViewModel非常狭隘,那么它可以完成这项工作。所以:

public class ViewModel : IValueConverter 
{ 
    // move your Convert and ConvertBack methods into here 
} 

现在你可以这样做:

<control:HierarchicalDataTemplate 
    ItemsSource="{Binding Converter={StaticResource ViewModel}}"> 
+0

这就是我要做的。不过,我不认为Silverlight允许在绑定中使用x:Static。这不正确吗? – herbrandson 2008-12-16 15:13:01

0

对不起大家好我有点困惑你正在尝试做的......总之,从标题听起来就好像你想要将值转换器中的属性转换为值转换器中的属性。首先看看在文章中,我已经写了解释究竟如何才能做到这一点: http://nick-howard.blogspot.com/2011/06/silverlight-4-value-converter.html

所以,你会做的是在你的LoadChildrenValueConverter创建ObvervableCollection依赖属性,为了讨论各种情形,让我们把它的孩子。

然后在你的XAML可以将LoadChildrenValueConverter改变这样的事情:

这样,你只能从您的视图模型调用Web服务一次,您就可以看到共享该ObvervableCollection在您的视图模型你的价值转换器。

希望有所帮助。

相关问题