UWP,当 ListView 的项目源是字符串集合时,将转换器应用于 ListView 的项目

UWP, Apply a converter to a ListView's item when the ListView's items source is a collection of strings

我有以下情况。我想显示一个字符串列表。为了实现这一点,我将一个 ListView 绑定到一个字符串集合。在这个集合中,有一些空字符串。我想要的是在存在空字符串时显示以下文本:“-empty-”。这是我目前得到的(源代码仅用于演示目的):

EmptyStringConverter.cs

public class EmptyStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value is string && string.IsNullOrWhiteSpace((string)value))
        {
            return "-empty-";
        }
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

MainPage.xaml

<Page
        x:Class="App1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">

    <Page.Resources>
        <local:EmptyStringConverter x:Key="EmptyStringConverter" />
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

        <ListView x:Name="ListView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Converter={StaticResource EmptyStringConverter}}" Margin="0,0,0,5" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        var source = new[] { "", "String 1", "String 2" };
        ListView.ItemsSource = source;
    }
}

当在 EmptyStringConverter 的 Convert 方法中放置断点时 class,除了空字符串外,每个项目都会调用该方法。我怎样才能达到我想要的?

好吧,问题出在我最后检查的地方。是您的 Legacy Binding 导致了这个问题。我自己尝试了一个代码片段,然后我用你的一段一段地替换了它。下面一行使用 legacy binding

Text="{Binding Converter={StaticResource EmptyStringConverter}}"

由于您使用的是 UWP,您可以切换到 Compile time binding,这将解决您的问题,您修改后的 ListView XAML 将是:

<ListView x:Name="ListView" >
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="x:String">
                <TextBlock Text="{x:Bind Converter={StaticResource EmptyStringConverter},Mode=OneTime}" Margin="0,0,0,5" />
            </DataTemplate>
        </ListView.ItemTemplate>
</ListView>

请注意两点:

  1. DataTemplateTextboxText 部分,它使用 x:Bind 而不是 Binding。请注意,编译时绑定默认是 oneTime 绑定(除非您明确提及模式),而旧版本 Binding 默认是 OneWay 绑定。有关编译时绑定的更多信息,请遵循:xBind markup extension.
  2. 如果您注意到 DataTemplate 声明包含 DataType 属性,这有助于编译时绑定器了解它期望的数据类型。有关 DataType 的更多信息,请关注:xBind markup extension.

综上所述,我强烈建议使用 Data Binding 方法而不是 ListView.ItemSource=source ,因为新的编译时绑定会导致很多转换由绑定引擎本身处理减少代码和工作量。我在 github 上放了一个样本,你可以查看:EmptyStringDemo