简体   繁体   English

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

[英]Windows Store App Change ItemTemplate OnClick/Dynamically

I have a ListView which has an ItemTemplateSelector that selects a template based on the data it gets from the service. 我有一个ListView,其中有一个ItemTemplateSelector,它根据从服务中获取的数据来选择模板。 In this case it is a list of items that have a Read vs Unread state. 在这种情况下,这是具有“已读”与“未读”状态的项目列表。 The selector works well on loading, but how can I change the template when an user clicks the item? 选择器在加载时效果很好,但是当用户单击项目时如何更改模板? Obviously I want the template to change when a user "reads" the data. 显然,我希望用户“读取”数据时更改模板。

View.xaml: View.xaml:

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

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

You have to build it in to your template. 您必须将其内置到模板中。 I suggest creating a custom UserControl for your data, which, when clicked/tapped/selected, hides the 'Unread' version and shows the 'Read' version. 我建议为您的数据创建一个自定义的UserControl,单击/点击/选择该控件时,将隐藏“未读”版本并显示“已读”版本。 You can bind the starting state to the data itself, or the ViewModel for the data. 您可以将起始状态绑定到数据本身,也可以将其绑定到数据的ViewModel。 Something like: 就像是:

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

Then, in the codebehind of your Usercontrol, declare a DependencyProperty (you can use the code snippet 'propdp'): 然后,在用户控件的代码中,声明一个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));

Then, create your PropertyChanged method to switch visual states! 然后,创建您的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);
    }
}

This should load properly, especially with the default value being false, but just in case it isn't, you may need to hook in to the control's Loaded event and set the VisualState to Unread from there. 应该正确加载,尤其是在默认值为false的情况下,但如果情况并非如此,则可能需要挂接到控件的Loaded事件,然后从此处将VisualState设置为Unread。

Lastly, you only need one Item Template, so get rid of the selector and just do: 最后,您只需要一个Item Template,因此摆脱选择器,然后执行以下操作:

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

Oh! 哦! There's actually one more thing to do. 实际上,还有另一件事要做。 Your ListView has to tell the item that it's been selected! 您的ListView必须告诉该项目已被选中! Add a SelectionChanged EventHandler (it will basically generate one for you). 添加一个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;
    }
}

Your Data/VM class will need to implement INotifyPropertyChanged. 您的Data / VM类将需要实现INotifyPropertyChanged。 If you're using a data VM, it should already do this. 如果您使用的是数据虚拟机,它应该已经执行了。

Happy Coding! 编码愉快!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM