1

サービスから取得したデータに基づいてテンプレートを選択する ItemTemplateSelector を持つ ListView があります。この場合、それは既読と未読の状態を持つアイテムのリストです。セレクターはロード時にうまく機能しますが、ユーザーがアイテムをクリックしたときにテンプレートを変更するにはどうすればよいですか? 明らかに、ユーザーがデータを「読み取る」ときにテンプレートを変更したいと考えています。

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

テンプレートに組み込む必要があります。クリック/タップ/選択すると、「未読」バージョンが非表示になり、「既読」バージョンが表示される、データ用のカスタム 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>

次に、ユーザー コントロールのコード ビハインドで、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 に設定する必要がある場合があります。

最後に、必要なアイテム テンプレートは 1 つだけなので、セレクターを削除して次のようにします。

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

おー!実はもう1つやるべきことがあります。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 を使用している場合は、既にこれが行われているはずです。

ハッピーコーディング!

于 2013-05-10T16:50:23.857 に答える