如何在 Universal Windows Apps 8.1 中显示和隐藏文本块

How to show and hide a Text Block in Universal Windows Apps 8.1

在面向 Windows Store 8.1 和 Windows Phone 8.1 的 Windows Universal Apps 8.1 平台中,我需要隐藏一个显示 "The list is empty" 的文本块当绑定到 ListView 的集合中有一些项目时,我需要在集合为空时显示此文本块。

请提出解决方案。

到目前为止我已经试过了,但是当集合中有项目时它不起作用元素 TasksEmptyMsg 仍然显示 "The list is empty".

<Page
    x:Class="ToDoer.Pages.Task"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ToDoer.Pages"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
    xmlns:core="using:Microsoft.Xaml.Interactions.Core"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView x:Name="Tasks"
                  ItemsSource="{Binding Tasks}"
                  SelectedItem="{Binding SelectedTask,Mode=TwoWay}"
                  ItemTemplate="{StaticResource TasksItemTemplate}"
                  Padding="24,24">
            <interactivity:Interaction.Behaviors>
                <core:EventTriggerBehavior EventName="SelectionChanged">
                    <core:InvokeCommandAction Command="{Binding TaskSelectionChanged}"/>
                </core:EventTriggerBehavior>
            </interactivity:Interaction.Behaviors>
        </ListView>

        <TextBlock x:Name="TasksEmptyMsg"
                   Text="The list is empty"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   Visibility="Collapsed"
                   Style="{StaticResource GroupHeaderTextBlockStyle}">
            <interactivity:Interaction.Behaviors>
                <core:DataTriggerBehavior Binding="{Binding ElementName=Tasks,Path=Items.Count}" 
                                          Value="0">
                    <core:ChangePropertyAction TargetObject="{Binding ElementName=TasksEmptyMsg}" 
                                               PropertyName="Visibility" 
                                               Value="Visible"/>
                </core:DataTriggerBehavior>
            </interactivity:Interaction.Behaviors>
        </TextBlock>
        <!--Uncomment to see an alignment grid to help ensure your controls are
            aligned on common boundaries.  The image has a top margin of -32px to
            account for the System Tray. Set this to 0 (or remove the margin altogether)
            if the System Tray is hidden.

            Before shipping remove this XAML and the image itself.-->
        <!--<Image Source="/Assets/AlignmentGrid.png" VerticalAlignment="Top" Height="800" Width="480" Margin="0,-32,0,0" Grid.Row="0" IsHitTestVisible="False" />-->
    </Grid>

    <Page.BottomAppBar>
        <CommandBar>
            <AppBarButton Icon="Add"
                          Label="add todo"
                          Command="{Binding AddTask}"/>
        </CommandBar>
    </Page.BottomAppBar>
</Page>

当集合中没有项目时工作正常。

问题:显示 "The list is empty",即使未显示。

ListView 本身没有任何 属性 通知它是空的,也没有绑定到 Items.Count 帮助这里,因为 属性 变化不是加注。值得庆幸的是,实现这种机制并不难,并且有几种方法可以实现。这是一个使用 Converters:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.Resources>
        <local:BoolToVisibility x:Key="BoolToVisibility"/>
    </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

    <ListView x:Name="TheList" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Tasks}" Visibility="{Binding IsTasksEmpty, Converter={StaticResource BoolToVisibility}, ConverterParameter='INVERT'}"/>
    <TextBlock x:Name="EmptyText" Grid.Column="0" Text="List is empty" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding IsTasksEmpty, Converter={StaticResource BoolToVisibility}}"/>
        <StackPanel Grid.Column="1">
            <Button Content="Add item" Click="AddButton_Click" Margin="20"/>
            <Button Content="Delete item" Click="DelButton_Click" Margin="20"/>
        </StackPanel>
</Grid>

和后面的代码:

public class BoolToVisibility : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language) => (bool)value != ((string)parameter == "INVERT") ? Visibility.Visible : Visibility.Collapsed;
    public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); }
}

public sealed partial class MainPage : Page, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

    public ObservableCollection<string> Tasks { get; set; } = new ObservableCollection<string>() { "Starting item" };
    public bool IsTasksEmpty => Tasks.Count < 1;

    public MainPage()
    {
        this.InitializeComponent();
        this.DataContext = this;
        Tasks.CollectionChanged += (sender, e) => RaiseProperty(nameof(IsTasksEmpty));
    }

    private void AddButton_Click(object sender, RoutedEventArgs e) => Tasks.Add("Next item");
    private void DelButton_Click(object sender, RoutedEventArgs e) => Tasks.RemoveAt(Tasks.Count - 1);
}

这是 UWP 的一个,它使用 VisualStates 和集合更改事件(看看你的代码,我假设你是使用 ObservableCollection 用于 Tasks)。 XAML代码:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="ListStates">
            <VisualState x:Name="ListWithItems"/>
            <VisualState x:Name="ListEmpty">
                <VisualState.Setters>
                    <Setter Target="EmptyText.Visibility" Value="Visible"/>
                    <Setter Target="TheList.Visibility" Value="Collapsed"/>
                </VisualState.Setters>
                <VisualState.StateTriggers>
                    <StateTrigger IsActive="{Binding IsTasksEmpty}"/>
                </VisualState.StateTriggers>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="300"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <ListView x:Name="TheList" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Tasks}"/>
    <TextBlock x:Name="EmptyText" Grid.Column="0" Text="List is empty" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed"/>
    <StackPanel Grid.Column="1">
        <Button Content="Add item" Click="AddButton_Click" Margin="20"/>
        <Button Content="Delete item" Click="DelButton_Click" Margin="20"/>
    </StackPanel>
</Grid>

后面的代码与上面的转换器解决方案相同。

UWP 的工作示例,您将 find at GitHub

我试图在 XAML 中解决这个问题,但到目前为止我无法做到,所以我尝试了另一种方法,即使用 BooleanToVisibilityConverter 绑定 TextBlock 的可见性 属性。

我设置了一个名为 AreTasksEmpty 的 属性,属性 通知是通过使用 MvvmLight 库完成的。

/// <summary>
/// The are tasks empty.
/// </summary>
private bool _areTasksEmpty;

/// <summary>
/// Gets or sets the are tasks empty.
/// </summary>
public bool AreTasksEmpty
{
    get
    {
        return this._areTasksEmpty;
    }
    set
    {
        this.Set(ref this._areTasksEmpty, value);
    }
}

在获取任务的方法中,我更新了 属性 AreTasksEmpty 的值,如下所示。

if (this.Tasks.Any())
{
    this.AreTasksEmpty = false;
}
else
{
    this.AreTasksEmpty = true;
}

在XAML中,我已经完成了对Visibility属性的绑定,如下所示,

<TextBlock x:Name="TasksEmptyMsg"
           Text="The list is empty"
           HorizontalAlignment="Center"
           VerticalAlignment="Center"
           Visibility="{Binding AreTasksEmpty, Converter={StaticResource BooleanToVisibilityConverter}}"
           Style="{StaticResource GroupHeaderTextBlockStyle}">
</TextBlock>