在 ListBox 中使用 DataTemplate
假設我們有以下 XAML 片段:
<ListBox x:Name="MyListBox" />
然後在這個 XAML 檔案的程式碼隱藏中,我們在建構函式中編寫以下內容:
MyListBox.ItemsSource = new[]
{
1, 2, 3, 4, 5
};
執行應用程式,我們得到一個我們輸入的數字列表。
但是,如果我們嘗試顯示自定義型別的物件列表,就像這樣
MyListBox.ItemsSource = new[]
{
new Book { Title = "The Hitchhiker's Guide to the Galaxy", Author = "Douglas Adams" },
new Book { Title = "The Restaurant at the End of the Universe", Author = "Douglas Adams" },
new Book { Title = "Life, the Universe and Everything", Author = "Douglas Adams" },
new Book { Title = "So Long, and Thanks for All the Fish", Author = "Douglas Adams" },
new Book { Title = "Mostly Harmless", Author = "Douglas Adams" }
};
假設我們有一個名為 Book
的類
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}
然後列表看起來像這樣:
雖然我們可以假設 ListBox 將足夠智慧來恰當地顯示我們的書籍物件,但我們實際看到的是 Book
型別的全名。ListBox 實際上在這裡做的是在它想要顯示的物件上呼叫內建的 ToString()
方法,雖然在數字的情況下產生了理想的結果,但在自定義類的物件上呼叫 ToString()
會導致獲得其型別的名稱,如在截圖上看到。
我們可以通過為我們的書類編寫 ToString()
來解決這個問題,即
public override string ToString()
{
return Title;
}
但是,這不是很靈活。如果我們想要展示作者怎麼辦?我們也可以將它寫入 ToString
,但如果我們不想在應用程式的所有列表中呢?如何展示漂亮的書籍封面?
這就是 DataTemplates 可以提供幫助的地方。它們是 XAML 的片段,可以根據需要例項化,根據建立的源資料填充詳細資訊。簡單地說,如果我們擴充套件 ListBox 程式碼如下:
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
然後列表將為其源中的每個項建立一個 TextBox
,這些 TextBox 將使用來自我們物件的 Title
屬性的值填充其 Text
屬性。
如果我們現在執行應用程式,我們將得到與上面相同的輸出,*即使我們刪除自定義 ToString
實現。對此有利的是,我們可以自定義此模板,遠遠超出簡單的 string
(和 ToString
)的功能。我們可以使用我們想要的任何 XAML 元素,包括自定義元素,並且可以將它們的值繫結到來自物件的實際資料(如上例中的 Title
)。例如,按如下方式擴充套件模板:
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock FontStyle="Italic" Text="{Binding Author}" />
<TextBlock FontSize="18" Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
然後我們得到了一個很好的格式化的書籍檢視!