datagrid WPF

时间:2016-05-17 18:56:24

标签: c# wpf xaml datagrid

我在WPF中使用带有C#,I' 4列的数据网格的应用程序,我需要相对于其他列计算四列。我使用的是IValueConverter,它可以很好地工作,但是当我更改行时只计算第四列的值,而当我更改单元格2和3时,我需要更改4列。

这是我的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();
    }
}

我该怎么做?

3 个答案:

答案 0 :(得分:4)

您的Item类需要实现INotifyPropertyChanged并在其任何属性发生更改时引发PropertyChanged事件。

然后麻烦的是,该绑定无法知道需要监视更改的属性。一种解决方案是将转换器更改为IMultiValueConverter,并将绑定更改为MultiBinding,该Price明确绑定CountTotalPrice

另一个选项,这将是一个更简单的选项,就是向您的Item类添加只读public decimal TotalPrice { get { return Price * Count; } } 属性。这就是我要做的。

Price

然后,在Price媒体资源中,当PropertyChanged发生变化时,您会引发TotalPrice以及Price的{​​{1}}事件。你会对Count做同样的事情。

然后你可以非常简单地在XAML中绑定到TotalPrice而根本没有转换器。您可能需要进行绑定Mode=OneWay,因为它是只读的。

如果您需要更多代码示例,请与我们联系。

答案 1 :(得分:1)

你必须使用IValueConverter。使用第一列作为源(将第二列绑定到第一列)并使用转换器转换值。

MSDN example

答案 2 :(得分:-1)

最后感谢Ed Plunkett,我在我的INotifyPropertyChanged课程中itemPrice强制Count强制调用OnPropertyChanged("TotalPrice")并完美地运作:< / p>

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;  }
    }
}