Windows应用商店应用更改ItemTemplate OnClick /动态

时间:2013-05-10 13:34:03

标签: c# windows-store-apps winrt-xaml

我有一个ListView,它有一个ItemTemplateSelector,它根据从服务中获取的数据选择模板。在这种情况下,它是具有读取与未读状态的项目列表。选择器在加载时效果很好,但是如何在用户单击项目时更改模板?显然,我希望在用户“读取”数据时更改模板。

View.xaml:

<Page.Resources>
    <selectors:MyItemTemplateSelector x:Key="NoteItemTemplateSelector" 
                                      ReadTemplate="{StaticResource MyReadTemplate}"
                                      UnreadTemplate="{StaticResource MyUnreadTemplate}"/>
</Page.Resources>

<ListView x:Name="ListView1"
         ItemTemplateSelector="{StaticResource MyItemTemplateSelector}"/>

1 个答案:

答案 0 :(得分:1)

您必须将其构建到模板中。我建议为您的数据创建一个自定义UserControl,当点击/点击/选中时,会隐藏“未读”版本并显示“读取”版本。您可以将起始状态绑定到数据本身,或将ViewModel绑定到数据。类似的东西:

<UserControl xmlns...>
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="DisplayStates">
                <VisualState x:Name="Read">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ReadContent">
                            <DiscreteObjectKeyFrame KeyTime="0">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Collapsed</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="UnreadContent">
                            <DiscreteObjectKeyFrame KeyTime="0">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Collapsed</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Unread">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="UnreadContent">
                            <DiscreteObjectKeyFrame KeyTime="0">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Collapsed</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ReadContent">
                            <DiscreteObjectKeyFrame KeyTime="0">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Collapsed</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Grid x:Name:"UnreadContent">
            <!--What it looks like when Unread-->
        </Grid>
        <Grid x:Name:"ReadContent">
            <!--What it looks like when Unread-->
        </Grid>
    </Grid>
</UserControl>

然后,在Usercontrol的代码隐藏中,声明一个DependencyProperty(您可以使用代码片段'propdp'):

public bool HasBeenRead
{
    get { return (bool)GetValue(HasBeenReadProperty); }
    set { SetValue(HasBeenReadProperty, value); OnHasBeenReadChanged(this, value); }
}

// Using a DependencyProperty as the backing store for HasBeenRead.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty HasBeenReadProperty =
    DependencyProperty.Register("HasBeenRead", typeof(bool), typeof(MyNewUserControl), new PropertyMetadata(false, OnHasBeenReadChanged));

然后,创建PropertyChanged方法以切换视觉状态!

private static void OnHasBeenReadChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if ((bool)e.NewValue)
    {
        VisualStateManager.GoToState(d as Control, "Read", true);
    }
    else
    {
        VisualStateManager.GoToState(d as Control, "Unread", true);
    }
}

这个应该正确加载,特别是默认值为false,但是如果不是,你可能需要挂钩控件的Loaded事件并将VisualState设置为Unread from那里。

最后,你只需要一个项目模板,所以摆脱选择器,然后执行:

<ListView.ItemTemplate>
    <DataTemplate>
        <!-- You'll have to import the namespace. Also, assumes that the item -->
        <!-- (or Item VM) has a "HasBeenRead" bool property -->
        <namespacewheremycontrolis:MyReadUnreadControl HasBeenRead="{Binding HasBeenRead}"/>
    </DataTemplate>
</ListView.ItemTemplate>

哦!实际上还有一个要做的事情。您的ListView必须告诉该项目已被选中!添加一个SelectionChanged EventHandler(它基本上会为你生成一个)。

private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if(sender != null && sender is ListView)
    {
        if(e.AddedItems.Count > 0)
            (e.AddedItems[0] as MyDataOrDataVMClass).HasBeenRead = true;
    }
}

您的Data / VM类需要实现INotifyPropertyChanged。如果您正在使用数据VM,它应该已经这样做了。

快乐的编码!