我有一个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}"/>
答案 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,它应该已经这样做了。
快乐的编码!