1

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

查看.xaml:

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

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

1 回答 1

1

您必须将其构建到您的模板中。我建议为您的数据创建一个自定义用户控件,当单击/点击/选择时,隐藏“未读”版本并显示“已读”版本。您可以将起始状态绑定到数据本身,或数据的 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>

然后,在您的用户控件的代码隐藏中,声明一个 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。

最后,您只需要一个项目模板,因此摆脱选择器并执行以下操作:

<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。如果您使用的是数据虚拟机,它应该已经这样做了。

快乐编码!

于 2013-05-10T16:50:23.857 回答