C# 在绑定的ListView中使用VisualStateGroup

C# 在绑定的ListView中使用VisualStateGroup,c#,xaml,win-universal-app,uwp,C#,Xaml,Win Universal App,Uwp,我在UWP中有一个绑定的listview,我想根据一些属性在ItemTemplate中显示或隐藏一些控件 我使用的XAML在这里用于绑定ObservableCollection <ListView x:Name="lvwMovieWatchlist" ItemsSource="{x:Bind Books}" Margin="10"> <ListView.ItemsPanel> <ItemsPanelTe

我在UWP中有一个绑定的listview,我想根据一些属性在ItemTemplate中显示或隐藏一些控件

我使用的XAML在这里用于绑定ObservableCollection

   <ListView x:Name="lvwMovieWatchlist"  ItemsSource="{x:Bind Books}" Margin="10">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <ItemsWrapGrid Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
            <ListView.ItemTemplate>              
                <DataTemplate x:DataType="data:BookModel">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Border Width="156" Height="200">
                            <Image Source="{Binding CoverImage}" Stretch="UniformToFill"/>
                        </Border>
                        <StackPanel Grid.Column="1" Orientation="Vertical">
                            <TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" Margin="9.6,0"/>
                            <TextBlock Text="{Binding Name}" Style="{StaticResource SubtitleTextBlockStyle}" TextWrapping="NoWrap" Margin="9.6,0"/>
                            <StackPanel Orientation="Horizontal" Margin="10">
                                <Button Name="Btn_Download" Tag="{Binding}" Click="Btn_Download_Click"> DOWNLOAD</Button>                                
                                <Button Name="Btn_Read" Tag="{Binding}" Click="Btn_Read_Click"> READ</Button>                                
                            </StackPanel>
                        </StackPanel>
                    </Grid>
                </DataTemplate>             
            </ListView.ItemTemplate>
        </ListView>

下载
阅读
这里有两个按钮Btn_Download和Btn_Read 如果Status属性为“read”,那么我想将Btn\u read的可见性设置为可见,否则显示Btn\u下载按钮

在WPF中,我有实现相同目标的触发器

        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Status}" Value="read">                   
                <Setter TargetName="Btn_Read" Property="Visibility" Value="Visible"/>
                <Setter TargetName="Btn_Download" Property="Visibility" Value="Collapsed"/>                 
            </DataTrigger>                                              
        </DataTemplate.Triggers>

但在UWP中没有触发器,只有VisualStateManager.VisualStateGroups可用。
那么,如何在ItemTemplate中使用VisualStateGroup呢?一个可能的想法是使用转换器而不是VisualStateManager:

<StackPanel Orientation="Horizontal" Margin="10">
                                        <Button Name="Btn_Download" Tag="{Binding}" Click="Btn_Download_Click" Visibility={Binding Status, Converter={StaticResource StatusToDownloadVisibilityConverter}}> DOWNLOAD</Button>                                
                                        <Button Name="Btn_Read" Tag="{Binding}" Click="Btn_Read_Click"  Visibility={Binding Status, Converter={StaticResource StatusToReadVisibilityConverter}}> READ</Button>                                
    </StackPanel>

下载
阅读
只需创建两个转换器(StatusToDownloadVisibilityConverter和StatusToReadVisibilityConverter),它们根据Status属性的值获取Status in参数并返回可见性


也许不是100%理想的解决方案,但这应该是可行的

如果您想完全在XAML中完成,可以使用扩展来完成。使用可视状态和datatriggeraction的示例可以如下所示-XAML:


背后的代码:

公共密封部分类主页面:第页,INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
public void RaiseProperty(字符串名称)=>PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(名称));
私有字符串status=“notRead”;
公共字符串状态
{
获取{返回状态;}
set{status=value;RaiseProperty(nameof(status));}
}
公共主页()
{
this.InitializeComponent();
DataContext=this;
}
私有无效按钮\u单击(对象发送者,路由目标e)=>Status=“读取”;
}
单击按钮可更改状态以读取并通过行为触发视觉状态更改。您可以对项目模板执行类似的操作。作为旁注,您还可以使用其他操作,根据您想要实现的目标,这些操作可能更容易一些-例如ChangePropertyAction


当然,要使其工作,您必须在项目中添加对行为的引用(添加引用->通用窗口->扩展),或者使用NuGet,诸如此类,这是一个更好的选择(开源和针对UWP)。

将模板包装在用户控件中,并添加可视化状态管理器

<ListView x:Name="lvwMovieWatchlist" ItemsSource="{x:Bind ViewModel.Books}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:BookModel">
            <local:BookControl />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

<UserControl
    x:Class="App2.BookControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App2"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">
        <Grid>
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="ButtonsVisibility">
                    <VisualState x:Name="ButtonsVisible">
                    </VisualState>
                    <VisualState x:Name="ButtonsHidden">
                        <VisualState.StateTriggers>
                            <StateTrigger IsActive="{Binding Status, Mode=OneWay}" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="Btn_Download.Visibility" Value="Collapsed" />
                            <Setter Target="Btn_Read.Visibility" Value="Collapsed" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <StackPanel Orientation="Vertical">
                <TextBlock Text="{Binding Title}" />
                <TextBlock Text="{Binding Subtitle}" />
                <StackPanel Orientation="Horizontal">
                    <Button Name="Btn_Download" Tag="{Binding}" Click="Btn_Download_Click">DOWNLOAD</Button>
                    <Button Name="Btn_Read" Tag="{Binding}" Click="Btn_Read_Click">READ</Button>
                </StackPanel>
            </StackPanel>
        </Grid>
</UserControl>

下载
阅读

此示例在布尔属性上使用内置StateTrigger。要将属性与您想要的某个值进行比较,请使用awesome WindowsStateTriggers库()中的EqualStateTrigger。

可以,但我喜欢使用VisualState,因为它可以完全控制xaml本身,想要了解VisualState的概念,我只想补充一点,最好通过Nuget添加Behaviors SDK,因为它现在的目标是UWP,并且是开源的。