2013-03-05 149 views
1

我是WPF的新手,所以請接受我的道歉,如果我的問題是愚蠢的。如何將自定義對象綁定到WPF中的ListBox

我正在創建一個由2個主要部分組成的食品訂購系統,即「食品菜單」和「訂單列表」。當用戶從食物菜單中選擇一個項目時,它將被添加到代表訂單列表的列表框控件中。

我已經創建了一些自定義對象:OrderOrderLineItem,以及集合類,OrderLineCollection,對於「訂單行」。他們看起來像下面這樣:

public class Order 
{ 
    public string ID { get; set; } 
    public DateTime DateTime { get; set; } 
    public double TotalAmt { get; set; } 
    public OrderLineCollection LineItems { get; set; } 
} 

public class OrderLine 
{ 
    public Item Item { get; set; } 
    public double UnitPrice { get; set; } 
    public int Quantity { get; set; } 
    public double SubTotal { get { return unitPrice * quantity; } } 
} 

[Serializable] 
public class OrderLineCollection : CollectionBase 
{ 
    public OrderLine this[int index] 
    { 
     get { return (OrderLine)List[index]; } 
     set { List[index] = value; } 
    } 
} 

public class Item 
{ 
    public string ID { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public double UnitPrice { get; set; } 
    public byte[] Image { get; set; } 
} 

ListBox控制具有DataTemplate讓更多詳細信息將顯示爲每個項目。在XAML如下:

<Page x:Class="FoodOrdering.OrderList" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Order List"> 
    <ListBox Name="lbxOrder" HorizontalContentAlignment="Stretch">    
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <Grid Margin="5"> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="30"/> 
         <ColumnDefinition Width="80"/> 
        </Grid.ColumnDefinitions> 
        <Grid.RowDefinitions> 
         <RowDefinition/> 
         <RowDefinition Height="40"/> 
        </Grid.RowDefinitions> 
        <TextBlock Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Text="{Binding item.name}"/> 
        <TextBlock Grid.Row="0" Grid.Column="1" Text="x "/> 
        <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding quantity}" Margin="10,0,0,0"/> 
        <TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding subTotal, Converter={StaticResource priceConverter}}" HorizontalAlignment="Right"/> 
        <Button Grid.Row="1" Grid.Column="2" Margin="0,5,0,0" Click="btnDelete_Click">Delete</Button> 
       </Grid> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
</Page> 

所以加入項目時,列表框將類似於下圖: https://dl.dropbox.com/u/6322828/orderList.png

在代碼隱藏,我創建了一個靜態變量currentOrder用於存儲當前順序,它將被其他類/方法使用。

每次更改其值時,將調用以下愚蠢的方法LoadCurrentOrder()來刷新ListBox視圖。

public partial class OrderList : Page 
{ 
    public static Order currentOrder = new Order(); 
    public OrderList() 
    { 
     InitializeComponent(); 
     LoadCurrentOrder(); 
    } 

    public void LoadCurrentOrder() 
    { 
     lbxOrder.Items.Clear(); 
     foreach (OrderLine ol in currentOrder.LineItems) 
      lbxOrder.Items.Add(ol); 
    } 
} 

我的問題是如何可以結合在一種優雅的方式的數據(例如使用ResourcesItemsSource等等),而不是使用上述方法,使得列表框將自動每次更新的值變量是否改變?

我試圖

lbxOrder.ItemsSource = currentOrder; 

,但它不工作作爲currentOrder不是System.Collections.IEnumerable對象。

回答

4

1 - 不創建自己的集合類型,.NET框架基類庫已經有你需要的幾乎一切。

刪除OrderLineCollection並使用ObservableCollection<OrderLine>

2 - 嘗試堅持使用MVVM約定。這意味着你不應該在代碼中操作UI元素。

public OrderList() 
{ 
    InitializeComponent(); 
    LoadCurrentOrder(); 
    DataContext = this; 
} 

然後在XAML:

<ListBox ItemsSource="{Binding LineItems}" HorizontalContentAlignment="Stretch"> 

3 - 除非你需要參考他們在XAML不要將其命名在XAML UI元素。這將幫助你每一次你發現自己想操縱程序代碼的UI元素的時間重新考慮你的方法。

4 - 習慣了C#命名約定。屬性名稱應該是「合適的裝箱」(I.E LineItems而不是lineItems

+0

感謝大會的提示特別是命名一個,想我搞砸了很長一段時間的概念......我已編輯的情況下,其他的屬性名稱可能會感到困惑 'ObservableCollection'在我的WPF項目工作正常。但是如果我在類庫項目中創建類,該怎麼辦?我試過了,它看起來像'ObservableCollection'只支持XAML用法? – pblyt 2013-03-06 10:58:39

+0

@pblyt的['System.Collections.ObjectModel.ObservableCollection '](http://msdn.microsoft.com/en-us/library/ms668604(V = VS.100)的.aspx)類中定義的' System.dll'組件,因此其是.NET BCL的核心部分,它不以任何方式依賴於任何WPF組件或類。 – 2013-03-06 14:54:08

0

您只需將lineItems屬性設置爲ObservableCollection<yourType>即可。然後,當此集合發生更改(項目添加,刪除)時,列表框將自動刷新。

如果您的問題是訂單本身發生變化,您需要刷新列表框。然後,您只需執行INotifyPropertyChanged,並在訂單更改時觸發屬性已更改的通知,並且UI將通過綁定進行刷新。

至於更優雅的方式綁定。您可以綁定到currentOrder.lineItems

lbxOrder.ItemsSource = currentOrder.lineItems;//this should be an observable collection if you intend to have items change 
+0

謝謝@dutzu,'ObservableCollection'在我的WPF項目中工作正常。但是,如果我在類庫項目中創建類並將其添加爲WPF項目中的參考,該怎麼辦?我試過了,它看起來像'ObservableCollection'只支持XAML用法。 – pblyt 2013-03-06 11:06:49

+0

您可以隨時換你從類庫得到作爲一個ObservableCollection以滿足您的需求,用戶界面對象的名單。 – dutzu 2013-03-06 12:08:45

相關問題