2013-04-10 15 views
10

私は以下のWindows RTアプリケーションを持っています。私は、List of Stringsを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をコレクションに設定したり、その理由を見たことがありません。 –

+0

これは単なるサンプルです。私が構築しているアプリケーションは、リストのタイプのプロパティを持つViewModelにDataContextを割り当てます。 –

答えて

5

TextBlockBindingにコンバーターを追加すると、実際にはバグ(または奇妙な意図的な機能)であることがわかります。あなたは上のブレークポイントを置く場合

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"/> 

は、このクラスを追加します。

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

が続いてコンバータを参照するためにバインディングを変更します。

は静的リソースを追加します。 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" }; 

暗黙的なキャストを使用すると、StringStringContextに変換するので、「動作する」だけです。はい、不要なクラスを作成するオーバーヘッドが追加されますが、機能します。 :)私はコンバータオプションを好むだろう。

+0

私はまた、何が起こっていたかを見るためのコンバータを作成しました。私はバグだと思う。私は変換器の仕事を使用します。ありがとう! –

+0

このバグにもRan。私はコードビハインドでより多くのことをやっていたので、もう少し情報があると思います。バインディングプロパティ 'TargetNullValue'が壊れているようです。空の文字列を指定すると、上記の動作が行われます。それに1つのスペース ''を与えた場合、それは単一のスペースでヌル値を埋めます。彼らは、単にnullと比較したいと思っていたシーンの背後にいくつかの 'IsNullOrEmpty'をしている可能性が高いです。 –

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または空のの場合、継承したDataContextに戻ります。私はこれがWinRTのバグだと思う。


また、あなたはまた、メインページクラスの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を設定せず、代わりにBinding Sourceを設定するために機能します。 – Clemens

0

実際、私は簡単な解決策を見つけました。これは間違いなくバグです。 WPFの同じコードでは、期待される結果が得られます。バグの原因は、空の文字列を正しく解釈しないTargetNullValueプロパティです。バグを回避するには、上で提案したIValueConverterを使用するか、経験者のパフォーマンス問題があるコンバータソリューションを使用するか、

 <TextBlock Text="{Binding TargetNullValue=' '}" FontSize="25"/> 
関連する問題