2013-04-10 85 views
10

我有以下Windows RT應用程序。我將一個字符串列表綁定到TextBlocks的ItemsControl。這會將空字符串顯示爲「System.Collections.Generic.List'1 [System.String]」,而不僅僅是一個空字符串。我希望它顯示一個空字符串,而不是DataContext的類型。TextBlock綁定顯示類名而不是空字符串

代碼後面:

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

XAML:

<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(); 
    } 
} 

XAML:

<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> 
+0

我沒有測試它,但它似乎是在平臺中的錯誤,但無論如何 - 這似乎不是使用綁定的典型主流方式。人們通常將ItemsSource直接設置爲集合或使用公開集合屬性的視圖模型類型,然後將該集合屬性綁定到您的ItemsControl的ItemsSource。我從來沒有見過任何人將DataContext設置爲集合,或者看到一個很好的理由。 – 2013-04-10 17:24:56

+0

這只是一個例子。我正在構建的應用程序將DataContext分配給具有List 類型屬性的ViewModel。 – 2013-04-10 18:31:24

回答

5

通過將轉換器添加到TextBlockBinding,您實際上可以看到它是一個錯誤(或奇怪的故意功能)。

添加靜態資源:

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

然後更改綁定引用轉換:如果您在把一個破發點

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(); 
    } 
} 

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

添加該類在return聲明中,您會看到實際傳遞的第一個值是整個列表。是的,意外。但是,如果您以書面形式使用此Converter,則它會處理這種奇怪的情況,並返回一個更具邏輯性的空字符串。

或者,你可以做更多的事情有趣並創建一個簡單的包裝類:

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" }; 

使用隱式強制轉換,它「只是起作用」,因爲它將String轉換爲StringContext。是的,它會增加創建不必要的類的開銷,但它確實有效。 :)我更喜歡轉換器選項。

+0

我也創建了一個轉換器來查看發生了什麼。我想這是一個錯誤。我將使用轉換器的工作。謝謝! – 2013-04-10 18:35:08

+0

也跑進這個bug。我在代碼隱藏方面更加努力,所以我想我有更多的信息。看起來綁定屬性'TargetNullValue'已損壞。如果你給它一個空字符串,你會得到上面描述的行爲。如果你給它一個空格「',那麼它將用單個空格填充空值。當他們想要與null比較時,他們可能會在幕後做一些'IsNullOrEmpty'。 – 2015-01-16 21:48:56

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

不是空字符串

顯然,當該項目結合的計算結果爲空或空,它回退到繼承的DataContext。我想這是WinRT中的一個錯誤。


另外,您也可以設置MainPage類的Name財產,寫一個結合是這樣的:

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

,而不是設置的DataContext:

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

,或者嘗試設置綁定代碼:

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

這對我有用。

+0

這可行,但不是因爲它的代碼隱藏。它的工作原理是因爲你不設置DataContext,而是綁定源。 – Clemens 2013-04-10 18:26:14

0

其實,我偶然發現了一個更簡單的解決方案。毫無疑問,這是一個錯誤。 WPF中的相同代碼給出了預期的結果。該bug的來源是TargetNullValue屬性,它不能正確解釋空字符串。爲了解決這個bug,你可以使用的IValueConverter建議以上(轉換器解決方案,從我的經驗性能問題),或者使用:

 <TextBlock Text="{Binding TargetNullValue=' '}" FontSize="25"/> 
相關問題