2016-05-17 41 views
1

私はWPFでC#でデータグリッドを持つアプリケーションを持っていましたが、私は4つのカラムを持っていましたが、4つのカラムは他のカラムに対して計算される必要があります。私はIValueConverterを使用していますが、これは完璧に動作しますが、行を変更すると列4の値が計算され、セル2と3を変更すると4列が変更されます。DataGridの計算カラムWPF

これは私のXAMLです:

<Window x:Class="WpfApplication6.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WpfApplication6" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <DataGrid Name="grid"> 
     <DataGrid.Resources> 
      <local:CalculatingConverter x:Key="CalculatingConverter" /> 
     </DataGrid.Resources> 
     <DataGrid.Columns> 
     <DataGridTextColumn Binding="{Binding Name}" /> 
     <DataGridTextColumn Binding="{Binding Count}"/> 
     <DataGridTextColumn Binding="{Binding Price}" /> 
     <DataGridTextColumn 
       Header="Total"     
       Binding="{Binding Converter={StaticResource CalculatingConverter}}" 
       /> 
    </DataGrid.Columns> 
    </DataGrid> 

</Grid> 

これは私のコードです:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     List<Item> items = new List<Item>(); 

     items.Add(new Item() { Name = "Item1", Count = 2, Price = 10 }); 
     items.Add(new Item() { Name = "Item2", Count = 5, Price = 20 }); 
     this.grid.ItemsSource = items; 
    } 
} 
public class Item : INotifyPropertyChanged 
{ 
    private string name; 
    private decimal price; 
    private int count; 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    public string Name {    
     get 
     { 
      return this.name; 
     } 

     set 
     { 
      if (value != name) 
      { 
       name = value; 
       OnPropertyChanged(); 
      } 
     } 
    } 
    public decimal Price 
    { 
     get 
     { 
      return price; 
     } 

     set 
     { 
      if (value != this.Price) 
      { 
       price = value; 
       OnPropertyChanged(); 
      } 
     } 
    } 
    public int Count { 
     get 
     { 
      return count; 
     } 

     set 
     { 
      if (value != count) 
      { 
       count = value; 
       OnPropertyChanged(); 
      } 
     } 
    } 
    public decimal TotalPrice 
    { 
     get { return Price * Count; } 
    } 
} 

そして、これは私のIConverterです:

public class CalculatingConverter : IValueConverter 
{ 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     try 
     { 

      return ((Item)value).Price * ((Item)value).Count; 
     } 
     catch 
     { 
      return null; 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

私はそれをどのように行うことができます?

+1

は、あなたがこれらの列の値はどこから来ている知っていますか? 「最初の列を直したり変更する」という意味を明確にすることはできますか? –

+0

私はそれが必要です、最初のカラムで値を変更すると、2番目のカラムも値を変更します。 – asirvent

+0

値の出所を知っていますか?どのようにグリッドに入れましたか? –

答えて

-1

エド・プランケットのおかげで私は私のitemクラスでINotifyPropertyChangedを実装し、PriceCount力にOnPropertyChanged("TotalPrice")に電話し、完璧に動作する:

public class Item : INotifyPropertyChanged 
{ 
    private string name; 
    private decimal price; 
    private int count; 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    public string Name {    
     get 
     { 
      return this.name; 
     } 

     set 
     { 
      if (value != name) 
      { 
       name = value; 
       OnPropertyChanged(); 
      } 
     } 
    } 
    public decimal Price 
    { 
     get 
     { 
      return price; 
     } 

     set 
     { 
      if (value != this.Price) 
      { 
       price = value; 
       OnPropertyChanged(); 
       OnPropertyChanged("TotalPrice"); 
      } 
     } 
    } 
    public int Count { 
     get 
     { 
      return count; 
     } 

     set 
     { 
      if (value != count) 
      { 
       count = value; 
       OnPropertyChanged(); 
       OnPropertyChanged("TotalPrice"); 
      } 
     } 
    } 
    public decimal TotalPrice 
    { 
     get { return Price * Count; } 
    } 
} 
1

これにはIValueConverterを使用する必要があります。最初の列をソースとして使用し(2番目の列を最初にバインドします)、コンバーターを使用して値を変換します。

MSDN example

4

クラスは、INotifyPropertyChangedを実装し、プロパティのいずれかが変更されたときにPropertyChangedイベントを発生させる必要があります。

問題は、そのバインディングが変更を監視する必要があるプロパティを知る方法がないことです。その1つの解決策は、コンバータをIMultiValueConverterに変更し、そのバインディングをPriceCountの両方を明示的にバインドするMultiBindingに変更することです。

あなたのためのもう1つのオプションは、これははるかに簡単なオプションで、プロパティをItemクラスに追加することです。それは私がやることです。 Price変更は、あなたがTotalPriceのためだけでなく、PriceためPropertyChangedイベントを発生させるでしょう、あなたのPrice財産で次に

public decimal TotalPrice { 
    get { return Price * Count; } 
} 

、、。そして、あなたはCountについて同じことをします。

次に、コンバータなしのXAMLで非常に簡単にTotalPriceにバインドできます。読み込み専用なので、バインディングをMode=OneWayにする必要があります。

もっとコード例が必要な場合は教えてください。最後に