2

假设我有以下 xaml ......

<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>

...以及以下代码...

使用系统;
使用 System.Collections.ObjectModel;
使用 System.Windows.Data;

命名空间 SilverlightViewModelSpike
{
    公共类视图模型
    {
        公共视图模型()
        {
            Root = new ObservableCollection() { "Item 1", "Item 2", "Item 3", };
        }

        公共 ObservableCollection 根 { 获取;私人套装;}        
    }

    公共类 LoadChildrenValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfoculture)
        {
            return new ObservableCollection() { "Item 1", "Item 2", "Item 3", };
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfoculture)
        {
            抛出新的 NotImplementedException();
        }
    }
}

这按预期工作,但感觉错误的是,我需要两个单独的类来获取视图所需的数据(想象一下 ViewModel 和 LoadChildrenValueConverter 从 Web 服务中提取数据而不是返回硬编码数据)。这里有更好的解决方案吗?我在想也许是这样的......

使用系统;
使用 System.Collections.ObjectModel;
使用 System.Windows.Data;

命名空间 SilverlightViewModelSpike
{
    公共类视图模型
    {
        公共视图模型()
        {
            Root = new ObservableCollection() { "Item 1", "Item 2", "Item 3", };
            ValueConverter = new LoadChildrenValueConverter();
        }

        公共 ObservableCollection 根 { 获取;私人套装;}
        公共 LoadChildrenValueConverter ValueConverter { get; 私人套装;}
    }

    公共类 LoadChildrenValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfoculture)
        {
            return new ObservableCollection() { "Item 1", "Item 2", "Item 3", };
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfoculture)
        {
            抛出新的 NotImplementedException();
        }
    }
}

...但是我无法让这条线工作...

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

...即使这似乎也不是一个很好的解决方案。有没有人对此有一个很好的干净解决方案?

4

2 回答 2

4

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

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

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

然后你可以简单地直接绑定到你的第二个属性:

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

我认为 ViewModel 对象的主要目的是限制从原始模型中获取所需数据所需的“技巧”(例如 IValueConverters)的数量。既然有,那就好好利用吧。

编辑 1

...当然,现在我重新阅读了您的帖子,我发现还有更多内容。您正在为“根”集合中的每个项目获取孩子。

如何将 IValueConverter 实现为 ViewModel 本身的静态实例?

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

现在你应该可以说:

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

编辑 2

好的,您使用的是 Silverlight,因此您无法使用 {x:Static}。

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

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

现在你可以这样做:

<control:HierarchicalDataTemplate
    ItemsSource="{Binding Converter={StaticResource ViewModel}}">
于 2008-12-16T04:45:12.343 回答
0

抱歉,伙计们,我对您在这里尝试做什么感到有些困惑...无论如何,从标题听起来好像您想将值转换器中的属性转换为值转换器中的属性。首先看看我写的一篇文章,解释你如何做到这一点:http: //nick-howard.blogspot.com/2011/06/silverlight-4-value-converter.html

所以你要做的是在你的 LoadChildrenValueConverter 中创建一个 ObvervableCollection 依赖属性,为了参数,我们称之为 Children。

然后在您的 xaml 中,您可以将 LoadChildrenValueConverter 更改为如下所示:

这样,您只需从您的视图模型中调用一次 Web 服务,然后您就可以在您的视图模型中与您的值转换器共享该 ObvervableCollection。

希望有帮助。

于 2011-06-09T05:35:54.580 回答