2017-03-07 52 views
0

我正在構建一個N層WPF應用程序。我想要零代碼隱藏。如何在WPF視圖模型中使用關係表

比方說,我有3個標準化的相關表來記錄銷售交易。

交易

TRANSACTIONID, 項目Id, 供應商ID, 價格

供應商

供應商ID, SupplierName

ITEMS

ItemId, ItemName。

對於每個表我有一個反映字段的基類。然後是根據需要填充基礎對象集合的數據層。

我想有一個展示的所有交易的列表頁面上的列表框,每行1個交易,行應該是這個樣子......

"Trainers FootLocker €99" 

"Trousers TopShop  €45" 

"Coat  TopShop  €49" 

如果我使用

<ListBox 
    ItemsSource="{Binding Path=Transactions}" 
    SelectedItem="{Binding CurrentTransaction}" 

然後我最終得到來自Transactions表的ID行,而不是來自Items和Suppliers表的Name值。

鑑於我有其他表填充只有ID的事務的集合,填充列表框的最佳方法是什麼?

我想知道的一件事是,如果我的事務基礎對象包含項目項填充那裏而不是int ItemId?

交易基本型號:

using System; 
using System.ComponentModel; 
using PFT; 
using PFT.Data; 

namespace PFT.Base 
{ 



    public class Transaction : INotifyPropertyChanged 
    { 

     public int Id { get; set; } 

     private int _itemId; 
     public int ItemId 
     { 
      get { return _itemId; } 
      set { 
       _itemId = value; 

       ItemData id = new ItemData(); 
       this.Item = id.Select(value); 

       NotifyPropertyChanged("ItemId"); 
      } 
     } 

     private Item _item; 

     public Item Item 
     { 
      get { return _item; } 
      set { _item = value; } 
     } 


     private float _price; 
     public float Price 
     { 
      get { return _price; } 
      set { 
       _price = value; 
       NotifyPropertyChanged("Price"); 
      } 
     } 

     private DateTime _date; 
     public DateTime Date 
     { 
      get { return _date; } 
      set { 
       _date = value; 
       NotifyPropertyChanged("Date"); 
      } 
     } 


     private string _comment; 
     public string Comment 
     { 
      get { return _comment; } 
      set 
      { 
       _comment = value; 
       NotifyPropertyChanged("Comment"); 
      } 
     } 

     private int _traderId; 
     public int TraderId 
     { 
      get { return _traderId; } 
      set 
      { 
       _traderId = value; 
       NotifyPropertyChanged("TraderId"); 
      } 
     } 

     private Trader _trader; 

     public Trader Trader 
     { 
      get { return _trader; } 
      set { _trader = value; 

      TraderData t = new TraderData(); 
      this.Trader = t.Select(value); 
      } 
     } 


     private string _insertType; 
     /// <summary> 
     /// A - Auto, M - Manual, V - Verified 
     /// </summary> 
     public string InsertType 
     { 
      get { return _insertType; } 
      set { _insertType = value; 
      NotifyPropertyChanged("InsertType"); 
      } 
     } 



     public event PropertyChangedEventHandler PropertyChanged; 
     // This method is called by the Set accessor of each property. 
     // The CallerMemberName attribute that is applied to the optional propertyName 
     // parameter causes the property name of the caller to be substituted as an argument. 
     //private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") 
     private void NotifyPropertyChanged(String propertyName = "") 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 

項基礎類

using System.ComponentModel; 

namespace PFT.Base 
{ 
    public class Item : INotifyPropertyChanged 
    { 
     private int _id; 

     public int Id 
     { 
      get { return _id; } 
      set { _id = value; 
      NotifyPropertyChanged("Id"); 
      } 
     } 



     private string _name; 

     public string Name 
     { 
      get { return _name; } 
      set { _name = value; 
      NotifyPropertyChanged("Name"); 
      } 
     } 


     private string _description; 

     public string Description 
     { 
      get { return _description; } 
      set { _description = value; 
      NotifyPropertyChanged("Description"); 
      } 
     } 


     private float _defaultPrice; 

     public float DefaultPrice 
     { 
      get { return _defaultPrice; } 
      set { _defaultPrice = value; 
      NotifyPropertyChanged("DefaultPrice"); 
      } 
     } 

     private bool _isIncome; 

     public bool IsIncome 
     { 
      get { return _isIncome; } 
      set { _isIncome = value; 
      NotifyPropertyChanged("IsIncome"); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     private void NotifyPropertyChanged(string propertyName = "") 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

    } 
} 
+0

你如何造型你的'ListBox'?默認情況下,'ListBox'只是在每個項目上調用'ToString'並顯示結果字符串。 –

+0

因此,基本上,您有3個集合(供應商,交易和物料),並且您想將它們加入到單個行中以顯示每個交易? –

+1

每個交易是否可以有多個供應商或物料? –

回答

1

你用的ViewModels做到這一點的方法是給Transaction一個Supplier財產和財產Item。這些屬性將引用自己集合中實際的ItemSupplier對象。如果每次交易的關係爲一個ItemID和一個SupplierID,則這是等價的對象。如果交易能夠多條記錄與同一交易ID和不同的供應商或產品標識,並Transaction需要收藏ItemSupplier。我們也可以在WPF中這樣做,但是它會比下面的簡單示例花費更多的尖括號。

你會設定,當您從數據庫中獲取您的項目(但你這樣做),或也許實體框架可以爲你做的。

真正簡單的列表框顯示項目名稱:添加DisplayMemberPath

<ListBox 
    ItemsSource="{Binding Transactions}" 
    SelectedItem="{Binding CurrentTransaction}" 
    DisplayMemberPath="Item.Name" 
    /> 

更復雜:

<ListBox 
    ItemsSource="{Binding Transactions}" 
    SelectedItem="{Binding CurrentTransaction}" 
    > 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock> 
       <Run Text="{Binding Item.Name, Mode=OneWay}" /> 
       <Run Text=" - " /> 
       <Run Text="{Binding Supplier.Name, Mode=OneWay}" /> 
       <Run Text=" " /> 
       <Run Text="{Binding Price, Mode=OneWay, StringFormat=c}" /> 
      </TextBlock> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

你也可以尋找到一個圓柱控制像ListViewDataGrid

稍微偏離主題,零代碼隱退有點極端。這是最後的手段,而不是第三軌。最小的代碼隱藏是一個合理的總體原則。不要爲了避免它而瘋狂;這是有原因的。

UPDATE

public class Transaction : INotifyPropertyChanged 
{ 
    // ... stuff ... 

    public Item Item 
    { 
     get { return _item; } 
     set { 
      _item = value; 
      // If this property is ever set outside the Transaction 
      // constructor, you ABSOLUTELY MUST raise PropertyChanged here. 
      // Otherwise, make the setter private. But just raise the event. 

      // This has nothing whatsoever to do with when or whether the Item 
      // class raises PropertyChanged, because this is not a property of the 
      // Item class. This is a property of Transaction. 

      NotifyPropertyChanged("Item"); 
     } 
    } 

    // ... more stuff ... 
+0

如果我的理解正確,我將Item項屬性添加到我的Transaction Base類中。然後這將是xaml中的T​​ransactions.Item.ItemName。 這種敲擊基礎類的純度。我想知道這是正確的做法嗎?我應該延長班級嗎?決定決定! –

+0

我在構建Xamarin多平臺手機應用程序,因此零代碼落後是理想選擇。我把它減少到每頁大約1行,設置datacontext - 這是非常好的,非常值得努力。 –

+0

*「這將是xaml中的T​​ransactions.Item.ItemName」* - 否,那根本行不通。 'Transactions'沒有'Item'屬性。 'Transactions'是某種集合類,希望'ObservableCollection '。 XAML將是我向你展示的內容。我沒有看到任何純度問題。你寫一個Transaction類的原因是模擬一個Item,一個Supplier和一個Price之間的關聯。 –

相關問題