2017-03-07 29 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之间的关联。 –

相关问题