1

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

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

父视图模型.cs

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

ChildViewModel.cs

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

主页.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 对象基于ChildViewModelProperty绑定到ItemTemplate

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

    ...
}

然后我更新了我的 LongListSelector 以使用我的(在 App.xaml 中声明为静态资源)转换器ItemTemplate直接绑定到我ChildViewModelProperty的类型,如下所示:MyEnumTypeMyConverter

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

现在,当我在设计器或模拟器中查看我的应用程序时,我的 LongListSelector 会输出一个列表,其中我的所有元素都显示为它们的.ToString()值(即它们的完全限定名称)。

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

我看到之前的一篇文章提到了一些关于 LLS 不处理模板更改的内容,但它有评论(在 2011 年)它已被修复。我想既然是 2013 年,那应该不再是问题了。

我错过了一些明显的东西,还是我需要更进一步?还是我一开始就用按钮做对了?

谢谢你的帮助!

4

1 回答 1

2

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

我为解决您的问题而采取的方法是实现一个自定义 DataTemplateSelector,它可以根据枚举值选择数据模板。

<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有一个如何实现这样一个选择器的例子

于 2013-06-20T15:35:23.517 回答