2010-08-27 47 views
1

我有一個對象集合,我想表示爲Grid,每個對象都表示爲Rectangle(或Button - 尚未解決)。每個對象都有一個X和一個Y屬性,它們代表它在Grid中的位置。如何顯示使用WPF中的網格的模板的項目集合?

例如,我可能有四種對象:

var one = new MyClass(){X=0, Y=0} 
var two = new MyClass(){X=1, Y=0} 
var three = new MyClass(){X=0, Y=1} 
var four = new MyClass(){X=1, Y=1} 

Grid應該有兩行兩列。對象one將在網格的左上部分表示爲Rectangle。對象two將位於對象one右側的插槽中,three將低於one,而four將位於右下角的插槽中。

我想弄清楚如何以慣用的WPF方式創建兩個模板(例如使用DataTemplate和類似的構造),但需要一些幫助。有什麼建議?

我也想能夠將模板存儲在我的主窗口的單獨文件中,但不知道如何做到這一點。

回答

1

一種方法是使用ListView。您可以設置它的ItemsPanel是一個畫布,然後在DataTemplate中的Canvas.Top和Canvas.Left綁定到你想要的項目有X和Y座標:

<ListView> 
    <ListView.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Canvas/> 
     </ItemsPanelTemplate> 
    </ListView.ItemsPanel> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <Button Canvas.Top="{Binding YPosition}", Canvas.Left="{Binding XPosition}"/> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

如果您需要您可以使用轉換器將YPosition和XPosition乘以單元格大小,以便這些屬性可以引用單元格編號而不是像素大小。


在其他(簡單)的手:如果事先知道有多少行或列網格將有且有一個且只有一個,每個電池元件,然後你可以使用一個UniformGrid而不是一個ListView。

+0

UniformGrid看起來很有前途,但它沒有ItemsSource屬性或支持ItemsPanel/ItemTemplate語法。數據綁定時如何使用它? – Pat 2010-08-27 17:08:17

+0

回答我自己的問題:http://stackoverflow.com/questions/1966258/chessboard-in-wpf/1966620#1966620 – Pat 2010-08-27 18:07:38

2

關於你的第一個問題,這可能是你要尋找的模式:

<ItemsControl> 
    <ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="100"/> 
      <ColumnDefinition Width="100"/> 
      <ColumnDefinition Width="100"/> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="50"/>   
      <RowDefinition Height="50"/>   
      <RowDefinition Height="50"/>   
     </Grid.RowDefinitions> 
     </Grid> 
    </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <Button Grid.Row="1" Grid.Column="2">R1C2</Button> 
    <Button Grid.Row="2" Grid.Column="1">R2C1</Button> 
    <Button Grid.Row="0" Grid.Column="0">R0C0</Button> 
</ItemsControl> 

在實際應用中,你會設置ItemsControl.ItemsSourceBinding源爲對象的集合,然後創建一個DataTemplate,如:

<DataTemplate DataType="{x:Type MyObject}"> 
    <Rectangle Grid.Row="{Binding Row}" Grid.Column="{Binding Column}"> 
    <!-- other visuals go here --> 
    </Rectangle> 
</DataTemplate> 

至於組織代碼放到單獨的文件中有云:你應該考慮,而不是一個用於顯示對象創建一個UserControl,。創建一個比其他對象更困難,並且UserControl是生活在他們自己的XAML文件中的類,可以像XAML一樣通過名稱與其他任何對象一起實例化。

根據您的設計,您可能會將網格定位從對象的實際視覺表示中分離出來,以便您可以在其他地方重新使用該表示。這可能是我的方法。創建我的對象UserControl後,我會創造Grid.Resources一個DataTemplate(因爲它是描述如何特定Grid應顯示對象)是這樣的:

<DataTemplate DataType="{x:Type MyObject}"> 
    <DockPanel Grid.Row="{Binding Row}" Grid.Column="{Binding Column}"> 
     <local:MyObjectUserControl DataContext="{Binding}"/> 
    </DockPanel> 
</DataTemplate> 

也有可能XAML使用包括樣組織方法:創建一個包含資源字典一個獨立的XAML文件,然後字典合併到你的窗口(或應用程序,或其他任何東西真的)資源字典:

<Window.Resources> 
    <ResourceDictionary> 
    <ResourceDictionary.MergedDictionaries> 
     <ResourceDictionary Source="myresourcedictionary.xaml"/> 
     <ResourceDictionary Source="myresourcedictionary2.xaml"/> 
    </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 
</Window.Resources> 

這可以是組織了很多好方法樣式和模板,儘管如此,如果設置了ResourceDictionary.MergedDictionaries,則不能直接在字典中放置任何項目,因此必須創建一個單獨的XAML文件來包含僅屬於該窗口的資源,這是一種痛苦。

+0

偉大的,徹底的答案羅伯特。非常感謝!我也發現了這個答案 - http://stackoverflow.com/questions/1966258/chessboard-in-wpf/1966620#1966620 - 有幫助。不幸的是,行和列綁定對我不起作用,但是當我終於弄明白這一切時,我會發布另一個答案。再次感謝! – Pat 2010-08-27 18:20:03

+0

那麼,我仍然沒有找到綁定到'Grid.Row'和'Grid.Column'的方法。我假設你的答案中的代碼實際上沒有在正確的行/列中顯示對象 - 或者它對你有用嗎? – Pat 2010-08-31 19:16:10

+0

我的錯誤。這就是爲什麼它不起作用:在'Button'上設置'Grid.Row'屬性只有在'Items'集合中的'Button'時纔有效。但是ItemsControl將每個模板項目放在一個容器中。該容器沒有'Grid.Row'或'Grid.Column'集合,因此'Grid'沒有看到它們。這就是'ItemContainerStyle'的用途。但我自己還沒有得到它的工作。當我這樣做時,我會發布一些內容。 – 2010-09-01 03:27:55