LongListSelector.ItemTemplate与IValueConverter绑定接收父视图模型对象而不是单个ItemsSource对象

时间:2013-06-19 17:27:34

标签: windows-phone-8 itemtemplate ivalueconverter longlistselector

由于某种原因,我的LongListSelector将其继承的DataContext传递给我的ItemTemplate转换器,导致列表项显示其默认的.ToString()值,而不是我的模板。

我最初将ItemTemplate定义为Button控件,其中Template绑定到绑定到LongListSelector的项的属性,并使用IValueConverter来获取正确的ControlTemplate:

ParentViewModel.cs

...
List<ChildViewModel> ChildViewModels { get; set; }
...

ChildViewModel.cs

...
MyEnumType MyEnumType { get; set; }
...

MainPage.xaml中

<phone:LongListSelector x:Name="MyLongListSelector"
                        IsGroupingEnabled="False"
                        ItemsSource="{Binding ChildViewModels}">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <Button Template="{Binding MyEnumType, Converter={StaticResource MyConverter}}" DataContext="{Binding}"/>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

这很好用,但我很确定我不需要将Button定义为数据模板,因为我应该能够根据LLS的选择事件捕获我需要的任何东西。

所以,试图做到正确(在我看来;这是我的第一个真正的WP8应用程序),我将所有模板从ControlTemplates更改为DataTemplates并更新了我的MyConverter以基于{{返回DataTemplate对象1}}绑定到ChildViewModelProperty

ItemTemplate

然后我更新了我的LongListSelector,将public class MyConverter : IValueConverter { public object Converter(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { MyEnumType enumType = MyEnumType.DefaultType; Enum.TryParse<MyEnumType>(value.ToString(), out enumType); DataTemplate template = null; switch (enumType) { case MyEnumType.Type1: template = (DataTemplate)App.Current.Resources["MyEmumTypeTemplate1"]; break; case MyEnumType.Type2: template = (DataTemplate)App.Current.Resources["MyEnumTypeTemplate2"]; break; default: template = (DataTemplate)App.Current.Resources["MyEnumTypeTemplateDefault"]; break; } return template; } ... } 直接绑定到ItemTemplateChildViewModelPropertyMyEnumType(在App.xaml中声明为静态资源)转换器如此:

MyConverter

现在,当我在设计器或模拟器中查看我的应用程序时,我的LongListSelector输出一个列表,其中所有元素都显示为<phone:LongListSelector x:Name="MyLongListSelector" IsGroupingEnabled="False" ItemsSource="{Binding ChildViewModels}" ItemTemplate="{Binding MyEnumType, Converter={StaticResource MyConverter}}" </phone:LongListSelector> 值(即其完全限定名称)。

我发现.ToString()被传递到ParentViewModel而不是每个MyConverter值。当我取出指定的Binding PropertyName(ChildViewModel.MyEnumType)并逐步调试调试器时,MyEnumProperty的类型为value,即LongListSelector的继承DataContext。当我为Binding输入我想要的属性名称时,它只是失败了绑定,甚至没有进入转换器。

我看到之前的一篇文章提到了LLS没有处理模板更改的问题,但它有一条评论(在2011年)已被修复。我认为自2013年以来,它不再是一个问题了。

我错过了一些明显的东西,还是我需要更进一步?或者我是否在第一时间用Button完成了这项工作?

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

问题在于,当您在LongListSelector的上下文中作为整体评估绑定时,此时数据上下文是ChildViewModels。在实施单个项目时不会重新评估。

我将解决您的问题的方法是实现一个自定义的DataTemplateSelector,它可以根据枚举值选择datatemplate。

<phone:LongListSelector x:Name="MyLongListSelector"
                        IsGroupingEnabled="False"
                        ItemsSource="{Binding ChildViewModels}">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <MyDataTemplateSelector Content="{Binding}">
                <MyDataTemplateSelector.Type1>
                    <DataTemplate>
                        // ... your content here
                    </DataTemplate>
                </MyDataTemplateSelector.Type1>
                <MyDataTemplateSelector.Type2>
                    <DataTemplate>
                        // ... your content here
                    </DataTemplate>
                </MyDataTemplateSelector.Type2>
                <MyDataTemplateSelector.Default>
                    <DataTemplate>
                        // ... your content here
                    </DataTemplate>
                </MyDataTemplateSelector.Default>
            </MyDataTemplateSelector>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

有一个如何在http://www.geekchamp.com/articles/implementing-windows-phone-7-datatemplateselector-and-customdatatemplateselector

实现这样一个选择器的例子