10

我有以下 Windows RT 应用程序。我将字符串列表绑定到 TextBlock 的 ItemsControl。这会将空字符串显示为“System.Collections.Generic.List'1[System.String]”,而不仅仅是一个空字符串。我希望它显示一个空字符串而不是 DataContext 的类型。

后面的代码:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext = new List<string>() { "", "not empty string" };
    }
}

xml:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Vertical"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}" FontSize="25"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

输出:

System.Collections.Generic.List'1[System.String]
non empty string

我用传统的 wpf 做了同样的例子,它正确显示了空字符串。

编辑 这输出相同的东西。

后面的代码:

public class Model
{
    private readonly List<string> items = new List<string>() { "", "non empty string" };

    public List<string> Items
    {
        get { return items; }
    } 
}

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext = new Model();
    }
}

xml:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <ItemsControl ItemsSource="{Binding Path=Items}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Vertical"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}" FontSize="25"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>
4

4 回答 4

5

通过将 Converter 添加到TextBlock Binding.

添加静态资源:

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

然后更改 Binding 以引用 Converter:

<TextBlock Text="{Binding Converter={StaticResource fixNulls}}" FontSize="25"/>

添加这个类:

public class NoNullsConverter : IValueConverter
{
    // This converts the value object to the string to display.
    public object Convert(object value, Type targetType,
        object parameter, string language)
    {
        return value is string ? value : "";         
    }

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

如果您在语句上放置一个断点return,您将看到实际传递的第一个值是整个列表。是的,出乎意料。但是,如果您按原样使用此转换器,它会处理这种奇怪的情况并返回一个更合乎逻辑的空字符串。

或者,您可以做一些更有趣的事情并创建一个简单的包装类:

public class StringContext
{
    public string Value { get; set; }
    public static implicit operator StringContext(string value)
    {
        return new StringContext() { Value = value };
    }

    public override string ToString()
    {
        return Value;
    }
}

使用此类,您可以按预期使用 Binding :

<TextBlock Text="{Binding}" FontSize="25"/>

但是,您需要在 List 的声明中使用不同的类类型:

DataContext = new List<StringContext>() { "", "not empty string" };

使用隐式转换,它“正常工作”,因为它将 转换StringStringContext. 是的,它会增加创建不必要的类的开销,但它确实有效。:) 我更喜欢 Converter 选项。

于 2013-04-10T17:40:35.880 回答
1

我真的无法解释为什么,但是当您直接设置ItemsSource属性时它会按预期工作:

<ItemsControl x:Name="itemsControl">
    ...
</ItemsControl>

public MainPage()
{
    this.InitializeComponent();
    itemsControl.ItemsSource = new List<string>() { "", "not empty string" };
}

我也试过这个:

<ItemsControl ItemsSource="{Binding Items}">
    ...
</ItemsControl>

public MainPage()
{
    this.InitializeComponent();
    Items = new List<string>() { "", "not empty string" };
    DataContext = this;
}

public IEnumerable Items { get; set; }

但它会导致显示

TextBlockBindingTest.MainPage

非空字符串

显然,当项绑定的计算结果为null 或 empty时,它会退回到继承的 DataContext。我猜这是WinRT中的一个错误。


或者,您也可以设置NameMainPage 类的属性并编写如下绑定:

<Page ... x:Name="mainPage">
...
<ItemsControl ItemsSource="{Binding Items, ElementName=mainPage}">
    ...
</ItemsControl>

并且不设置DataContext:

public MainPage()
{
    this.InitializeComponent();
    Items = new List<string>() { "", "not empty string" };
}
于 2013-04-10T17:14:17.343 回答
0

实际上,我偶然发现了一个更简单的解决方案。毫无疑问,这是一个错误。WPF 中的相同代码给出了预期的结果。错误的来源是 TargetNullValue 属性,它不能正确解释空字符串。要解决该错误,您可以使用上面建议的 IValueConverter(根据我的经验,Converter 解决方案存在性能问题)或使用:

        <TextBlock Text="{Binding TargetNullValue=' '}" FontSize="25"/>
于 2015-01-16T22:11:38.403 回答
0

或尝试在后面设置绑定代码:

//list is ItemsControl
var bin = new Binding();
var mylist = new List<string>(){"","not empty string"};
bin.Source = mylist;
list.SetBinding(ItemsControl.ItemsSourceProperty,bin);

这对我有用。

于 2013-04-10T17:35:39.310 回答