2016-11-28 20 views
0

enter image description here表示総販売

私はデータグリッドでの合計金額の合計にUI上の総販売テキストボックスをバインドする方法を理解する問題を抱えています。私はいくつかの記事を読んで、サムプロシージャを実装しようとし、それをバインドし、コレクションの通知を変更しようとしたと私は働くためにトータルセールを得ることができません。数量または単価が変更されたときに自動的に更新される計算済TotalPriceを持つQuantityおよびUnitPriceプロパティを持つアイテムクラスがあります。項目のリストは、SalesOrderクラスに含まれています。 uiは私が注文を作成するために使用しているメインウィンドウです。 私のコードは以下にあります:https://github.com/battondl/SalesOrder/tree/master/simpleShoppingListProgram UIテキストボックスの合計金額を自動的に更新する方法については、大変お世話になります。

データグリッドの各広告申込情報には、quanity *単価に基づいた合計価格が設定されています。

それは私がすべてのラインアイテムのtotalpriceの合計である更新しようとしている総販売価格です。

class Item : INotifyPropertyChanged 
{ 
    private string partNumber; 
    private int quantity; 
    private decimal unitPrice; 
    private DateTime orderDate; 


    public string PartNumber 
    { 
     get { return partNumber; } 
     set 
     { 
      partNumber = value; 
      OnPropertyChanged(); 
     } 
    } 

    public int Quantity 
    { 
     get { return quantity; } 
     set 
     { 
      quantity = value; 
      OnPropertyChanged("Quantity"); 
      OnPropertyChanged("TotalPrice"); 
     } 
    } 
    public decimal UnitPrice 
    { 
     get { return unitPrice; } 
     set 
     { 
      unitPrice = value; 
      OnPropertyChanged("UnitPrice"); 
      OnPropertyChanged("TotalPrice"); 
     } 
    } 

    public DateTime OrderDate 
    { 
     get { return orderDate; } 
     set 
     { 
      orderDate = value; 
      OnPropertyChanged(); 
     } 
    } 

    public decimal TotalPrice => Quantity * UnitPrice; 

    public Item() 
    { 
     PartNumber = ""; 
     Quantity = 0; 
     UnitPrice = 0.00m; 
     OrderDate = DateTime.Now; 
    } 


    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged([CallerMemberName] string caller = "") 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(caller)); 
     } 
    } 


} 



class SalesOrder 
{ 

    private string orderNumber; 
    public string OrderNumber 
    { 
     get { return orderNumber; } 
     set 
     { 
      orderNumber = value; 
     } 
    } 

    private ObservableCollection<Item> items; 

    public ObservableCollection<Item> Items 
    { 
     get { return items; } 
    } 

    public SalesOrder() 
    { 
     orderNumber = ""; 
     items = new ObservableCollection<Item>(); 

    } 

    public decimal CalculateTotalPrice() 
    { 
     decimal total = 0.00m; 
     foreach (Item item in items) 
     { 
      total += item.TotalPrice; 
     } 
     return total; 
    } 
} 

public partial class MainWindow : Window 
{ 
    private SalesOrder salesOrder; 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     salesOrder = new SalesOrder(); 
     dgSaleItems.ItemsSource = salesOrder.Items; 

     tbx_totalSale.Text = salesOrder.CalculateTotalPrice().ToString(); 
    } 
} 


<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="6*"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 
    <StackPanel Orientation="Vertical" 
     Grid.Row="0"> 
     <StackPanel Orientation="Horizontal"> 
      <Label Content="OrderNumber: " /> 
      <TextBox Name="tbx_orderNumber" 
        Width="100"/> 
     </StackPanel> 
    </StackPanel> 
    <StackPanel Orientation="Vertical" 
       Grid.Row="1"> 
     <DataGrid Name="dgSaleItems" 
     Grid.Row="1" 
        AutoGenerateColumns="False"> 
      <DataGrid.Columns> 
       <DataGridTextColumn x:Name="partNumber" 
            Header="Part Number" 
            Binding="{Binding Path=PartNumber}" /> 
       <DataGridTextColumn x:Name="quantity" 
            Header="Quantity" 
            Binding="{Binding Path=Quantity}" /> 
       <DataGridTextColumn x:Name="unitPrice" 
            Header="Unit Price" 
            Binding="{Binding Path=UnitPrice}" /> 
       <DataGridTextColumn x:Name="totalPrice" 
            Header="Total Price" 
            Binding="{Binding Path=TotalPrice}" /> 
       <DataGridTemplateColumn x:Name="orderDate" 
             Header="Order Date"> 
        <DataGridTemplateColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding Path=OrderDate}"   /> 
          </DataTemplate> 
         </DataGridTemplateColumn.CellTemplate> 
         <DataGridTemplateColumn.CellEditingTemplate> 
          <DataTemplate> 
          <DatePicker SelectedDate="{Binding Path=OrderDate}" /> 
          </DataTemplate> 
         </DataGridTemplateColumn.CellEditingTemplate> 
        </DataGridTemplateColumn> 
      </DataGrid.Columns> 
     </DataGrid> 
    </StackPanel> 
    <StackPanel Orientation="Vertical" 
       Grid.Row="7"> 
     <StackPanel Orientation="Horizontal"> 
      <Label Content="Total Sale: " /> 
      <TextBox x:Name="tbx_totalSale" 
        Width="100"/> 
     </StackPanel> 
    </StackPanel> 
</Grid> 
+1

は疑問に関連するコードをしてください置きます。もしあれば、「トータルセールス」と「トータルプライス」の違いについても説明してください。彼らが同じであれば、解決しようとしている問題は何ですか?彼らが違うなら、同じ方法で両方をやってみませんか? –

+0

私はtxtboxに全く拘束されていません...コードを投稿すると助けになります... –

+0

合計金額は数量で計算された単価です*単価。私はそれが機能しなかったので、非作業バインディングを取り出した。合計売上は、すべての広告申込情報の合計価格の合計です。 – Hippie

答えて

0
private void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    salesOrder = new SalesOrder(); 
    dgSaleItems.ItemsSource = salesOrder.Items; 

    tbx_totalSale.Text = salesOrder.CalculateTotalPrice().ToString(); 
} 

あなただけのウィンドウのloadイベント中に一度の総販売を更新している、しかし、あなたはまた、それを、アイテムの数量や価格が変更されるたびに更新する必要が忘れています。ここで

は、あなたがそれを行うことができます方法は次のとおりです。理想的には

private void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    salesOrder = new SalesOrder(); 
    dgSaleItems.ItemsSource = salesOrder.Items; 

    salesOrder.Items.CollectionChanged += (s, args) => 
    { 
     if (args.Action == NotifyCollectionChangedAction.Remove) 
     { 
      foreach (Item item in args.OldItems) 
      { 
       item.PropertyChanged -= UpdateTotalSale; 
      } 
     } 
     else if (args.Action == NotifyCollectionChangedAction.Add) 
     { 
      foreach (Item item in args.NewItems) 
      { 
       item.PropertyChanged += UpdateTotalSale; 
      } 
     } 
    }; 
} 

private void UpdateTotalSale(object sender, PropertyChangedEventArgs e) 
{ 
    tbx_totalSale.Text = salesOrder.CalculateTotalPrice().ToString(); 
} 

、あなたはSalesOrderINPCを実装し、コードの後ろに、できるだけ清潔に保つ必要がありますよう、SalesOrder内の上記のコードを移動する必要があります。

+0

ありがとう、私はそれをすべて一緒に持って完了するために必要な支援を提供しました。私はまた、あなたが提案したSalesOrderクラスへの実装方法を理解することができました! – Hippie

0

何のテキストボックスにバインディングがありません:

<TextBox x:Name="tbx_totalSale" 
       Width="100"/> 

それはする必要があります:

<TextBox x:Name="tbx_totalSale" 
     Text="{Binding TotalSale}" 
       Width="100"/> 

、あなたは合計を返しますあなたのSaleOrderクラスにTotalSaleプロパティを追加する必要があります

public decimal TotalSale 
{ 
    get { return items.Sum(i => i.TotalPrice); 
} 
:行

コレクションにアイテムを追加または削除するとき、またはTotalPrice行が変更されたときに、OnPropertyChanged("TotalSale")イベントを発行する必要があります。数量または単価のいずれかが変更された場合はすでにTotalPriceを更新していますので、その変更をitemsコレクションに上向きに伝播するだけです。

+0

これは動作しますが、1回だけです。アイテムのプロパティも変更して購読し、 'TotalSale'を変更する必要があるときに通知する必要があります。 – Xiaoy312

+0

@ Xiaoy312 - 確かに。 – ChrisF

+0

ありがとう、私は複数の答えにフラグを付けることができたらいいと思います。 – Hippie

0

enter image description here

おかげで、私はそれが今働いています!私は修正/ SalesOrderクラスにフォローを追加しました

public decimal TotalSale 
    { 
     get { return items.Sum(i => i.TotalPrice); } 

    } 

    public SalesOrder() 
    { 
     orderNumber = ""; 
     items = new ObservableCollection<Item>(); 

     Items.CollectionChanged += (s, args) => 
     { 
      if (args.Action == NotifyCollectionChangedAction.Remove) 
      { 
       foreach (Item item in args.OldItems) 
       { 
        item.PropertyChanged -= UpdateTotalSale; 
       } 
      } 
      else if (args.Action == NotifyCollectionChangedAction.Add) 
      { 
       foreach (Item item in args.NewItems) 
       { 
        item.PropertyChanged += UpdateTotalSale; 
       } 
      } 
     }; 

    } 

    private void UpdateTotalSale(object sender, PropertyChangedEventArgs e) 
    { 

     foreach (Window window in Application.Current.Windows) 
     { 
      if (window.GetType() == typeof(MainWindow)) 
      { 
       (window as MainWindow).tbx_totalSale.Text =   CalculateTotalPrice().ToString(); 
      } 
     } 

    } 

私はまた、XAMLに次を追加しました。

<StackPanel Orientation="Vertical" 
       Grid.Row="7"> 
    <StackPanel Orientation="Horizontal"> 
      <Label Content="Total Sale: " /> 
      <TextBox x:Name="tbx_totalSale" 
        Text="{Binding TotalSale}" 
        Width="100" 
        x:FieldModifier="public"/> 
</StackPanel> 

そして最後に、背後にあるコードには、この:

private void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    salesOrder = new SalesOrder(); 
    dgSaleItems.ItemsSource = salesOrder.Items; 

}