2016-05-17 19 views
1

У меня есть приложение с datagrid в WPF с C#, у меня 4 столбца, и мне нужно, чтобы четыре столбца вычислялись по отношению к другим столбцам. Я использую IValueConverter, который работает отлично, но только вычисляет значения столбца четыре, когда я меняю строку, и мне нужно, чтобы при изменении ячейки 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

Мне нужно, чтобы в первом столбце менялось значение, а затем значение второго столбца. – asirvent

+0

Знаете ли вы, откуда взялись эти значения? Как вы положили их в сетку? –

ответ

-1

Наконец, благодаря Эд Планкетт я реализовать INotifyPropertyChanged в моем item классе и в Price и Count силы позвонить в 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. Используйте первый столбец в качестве источника (сначала привяжите второй столбец) и преобразуйте значение с помощью вашего конвертера.

MSDN example.

4

Ваш класс Item должен реализовать INotifyPropertyChanged и поднять событие PropertyChanged, если какое-либо его изменение изменится.

Проблема в том, что для этого привязки нет способа узнать, какие свойства необходимо наблюдать за изменениями. Одним из решений этого является изменение вашего конвертера на IMultiValueConverter и изменение этого привязки к MultiBinding, который явно связывает и Price, и Count.

Другой вариант для вас, и это было бы намного проще, было бы добавить только свойство TotalPrice для вашего Item. Это то, что я сделал бы.

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

Тогда в вашем Price собственности, когда Price изменения, вы бы поднять PropertyChanged событие для TotalPrice, а также для Price. И вы сделаете то же самое для Count.

Тогда вы можете привязать к TotalPrice очень просто в XAML без конвертера вообще. Возможно, вам понадобится сделать привязку Mode=OneWay, так как она только для чтения.

Дайте мне знать, если вам нужно больше примеров кода.

Смежные вопросы