我在UWP中有一个绑定的列表视图,我想根据一些属性在ItemTemplate中显示或隐藏一些控件
<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_Read的可见性设置为Visible,否则显示Btn_Download按钮
在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来实现它呢
发布于 2015-12-15 18:51:46
一种可能的想法是使用转换器而不是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>只需创建2个转换器(StatusToDownloadVisibilityConverter和StatusToReadVisibilityConverter),它们接受参数中的状态,并根据状态属性的值返回可见性。
也许不是100%理想的解决方案,但这应该是可行的!
发布于 2015-12-15 20:22:29
如果你想完全用XAML实现,你可以使用Interactivity behaviors扩展。使用可视状态和数据触发操作的示例可能如下所示- XAML:
<Grid xmlns:i="using:Microsoft.Xaml.Interactivity" xmlns:ic="using:Microsoft.Xaml.Interactions.Core" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ReadOrNot">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Read">
<Storyboard BeginTime="0:0:0" Duration="0:0:1">
<FadeOutThemeAnimation TargetName="BtnDownload"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<i:Interaction.Behaviors>
<i:BehaviorCollection>
<ic:DataTriggerBehavior Binding="{Binding Status}" Value="read">
<ic:GoToStateAction StateName="Read"/>
</ic:DataTriggerBehavior>
</i:BehaviorCollection>
</i:Interaction.Behaviors>
<Button Name="BtnDownload" HorizontalAlignment="Left" Content="Download" FontSize="20" Foreground="Red"/>
<Button HorizontalAlignment="Center" Content="Change property" FontSize="20" Foreground="Orange" Click="Button_Click"/>
<Button Name="BtnRead" HorizontalAlignment="Right" Content="Read" FontSize="20" Foreground="Green"/>
</Grid>后面的代码:
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
private string status = "notRead";
public string Status
{
get { return status; }
set { status = value; RaiseProperty(nameof(Status)); }
}
public MainPage()
{
this.InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e) => Status = "read";
}按钮单击会将状态更改为已读,并通过行为触发视觉状态更改。您可以对您的项目模板执行类似的操作。作为附注,您还可以使用其他操作,这些操作可能会更容易一些,具体取决于您想要实现的目标--例如ChangePropertyAction。
当然,要让它工作,你必须在你的项目中添加对行为的引用(Add reference -> Universal windows -> Extensions),或者通过NuGet添加引用,就像igrali has mentioned一样,是一个更好的选择(开源和瞄准UWP)。
发布于 2015-12-16 00:35:16
将模板包装在用户控件中,并添加可视化状态管理器。
<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。要将属性与某个值进行比较,可以使用令人敬畏的WindowsStateTriggers库(https://github.com/dotMorten/WindowsStateTriggers)中的EqualsStateTrigger。
https://stackoverflow.com/questions/34287130
复制相似问题