Xaml TextBlock绑定显示类名而不是空字符串

Xaml TextBlock绑定显示类名而不是空字符串,xaml,binding,windows-runtime,microsoft-metro,winrt-xaml,Xaml,Binding,Windows Runtime,Microsoft Metro,Winrt Xaml,我有以下Windows RT应用程序。我将字符串列表绑定到文本块的ItemsControl。这将把空字符串显示为“System.Collections.Generic.List'1[System.String]”,而不仅仅是一个空字符串。我希望它显示一个空字符串,而不是DataContext的类型 代码隐藏: public sealed partial class MainPage : Page { public MainPage() { this.Initial

我有以下Windows RT应用程序。我将字符串列表绑定到文本块的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" };
    }
}
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();
    }
}
//list is ItemsControl
var bin = new Binding();
var mylist = new List<string>(){"","not empty string"};
bin.Source = mylist;
list.SetBinding(ItemsControl.ItemsSourceProperty,bin);
我用传统的wpf做了同样的例子,它正确地显示了空字符串

编辑 这输出相同的东西

代码隐藏:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext = new List<string>() { "", "not empty string" };
    }
}
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();
    }
}
//list is ItemsControl
var bin = new Binding();
var mylist = new List<string>(){"","not empty string"};
bin.Source = mylist;
list.SetBinding(ItemsControl.ItemsSourceProperty,bin);
公共类模型
{
私有只读列表项=新列表(){“”“非空字符串”};
公共清单项目
{
获取{返回项;}
} 
}
公共密封部分类主页面:第页
{
公共主页()
{
this.InitializeComponent();
DataContext=新模型();
}
}
xaml:


我真的无法解释原因,但当您直接设置
ItemsSource
属性时,它会正常工作:

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

public MainPage()
{
    this.InitializeComponent();
    itemsControl.ItemsSource = new List<string>() { "", "not empty string" };
}
并且不设置DataContext:

public MainPage()
{
    this.InitializeComponent();
    Items = new List<string>() { "", "not empty string" };
}
public主页()
{
this.InitializeComponent();
Items=新列表(){“”“非空字符串”};
}

或尝试将绑定代码设置为隐藏:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext = new List<string>() { "", "not empty string" };
    }
}
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();
    }
}
//list is ItemsControl
var bin = new Binding();
var mylist = new List<string>(){"","not empty string"};
bin.Source = mylist;
list.SetBinding(ItemsControl.ItemsSourceProperty,bin);
//列表是ItemsControl
var bin=新绑定();
var mylist=new List(){“”“非空字符串”};
bin.Source=mylist;
list.SetBinding(ItemsControl.ItemsSourceProperty,bin);

这对我很有效。

通过向
TextBlock
绑定添加一个转换器,实际上可以看出这是一个bug(或奇怪的故意功能)

添加静态资源:

<Page.Resources>
    <local:NoNullsConverter x:Key="fixNulls"></local:NoNullsConverter>
</Page.Resources>
如果在
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;
    }
}
使用此类,您可以按预期使用绑定:

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

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

DataContext = new List<StringContext>() { "", "not empty string" };
DataContext=newlist(){“”“非空字符串”};

使用隐式转换,它将
String
转换为
StringContext
,从而“只起作用”。是的,这会增加创建不必要的类的开销,但确实有效。:)我更喜欢转换器选项

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



我还没有测试过它,但它似乎是平台中的一个bug,但无论如何,这似乎不是使用绑定的典型主流方式。人们通常会直接将ItemsSource设置为集合,或者使用一种视图模型类型来公开集合属性,然后将该集合属性绑定到ItemsControl的ItemsSource。我从未见过任何人将DataContext设置为集合,也没有看到这样做的好理由。这只是一个示例。我正在构建的应用程序将DataContext分配给一个ViewModel,该ViewModel的属性类型为List。它之所以有效,是因为您没有设置DataContext,而是设置绑定源。我想这是一只虫子。我将使用转换器工作。谢谢也遇到了这个bug。我更多的是使用代码隐藏,所以我想我有更多的信息。绑定属性“TargetNullValue”似乎已损坏。如果给它一个空字符串,则得到上面描述的行为。如果为其提供单个空间“”,则它将使用单个空间填充空值。他们可能在幕后做了一些“IsNullOrEmpty”,而他们只是想与null进行比较。
DataContext = new List<StringContext>() { "", "not empty string" };
        <TextBlock Text="{Binding TargetNullValue=' '}" FontSize="25"/>