Заголовок группы DataGrid не обновляется при новой записи - PullRequest
0 голосов
/ 27 декабря 2018

У меня проблемы с обновлением заголовка группировки DataGrid.Когда я добавляю или удаляю запись, итоговая сумма не обновляется, если я не прибегаю к ней, а иногда даже редактирование суммы не обновляет итоговую сумму.Я добавил INotifyPropertyChanged, IEditableObject и IsLiveGroupingRequested в соответствии с предложениями некоторых сообщений на форуме, которые я прочитал без удачи.Я установил точку останова в функции конвертера и заметил, что она не запускается, когда я добавляю / удаляю / редактирую запись, она не запускается, пока я не отсортирую таблицу.Я не уверен, что я делаю здесь неправильно.

xaml

<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        xmlns:s="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <local:Converter1 x:Key="c1"/>
        <CollectionViewSource x:Key="cvs1" Source="{Binding Path=Lines, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="Type"/>
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </Window.Resources>

    <DataGrid Name="_dataGrid1" ItemsSource="{Binding Source={StaticResource cvs1}}">
        <DataGrid.GroupStyle>
            <GroupStyle>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="GroupItem">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="GroupItem">
                                    <StackPanel>
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*"/>
                                                <ColumnDefinition Width="Auto"/>
                                            </Grid.ColumnDefinitions>
                                            <Label Grid.Column="0" Content="{Binding Path=Name}" Padding="0"/>
                                            <Label Grid.Column="1" Content="{Binding Converter={StaticResource c1}}" Padding="0"/>
                                        </Grid>
                                        <ItemsPresenter/>
                                    </StackPanel>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>
        </DataGrid.GroupStyle>
    </DataGrid>

</Window>

codebehind

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;

namespace WpfApp2
{

    public partial class MainWindow : Window
    {

        public MainWindow()
        {

            InitializeComponent();


            Transaction transaction = new Transaction();
            transaction.Lines.Add(new TransactionLine() { Account = "ACCOUNT1", Type = "ACCOUNT", Amount = -41.86 });
            transaction.Lines.Add(new TransactionLine() { Account = "BUDGET1", Type = "BUDGET", Amount = 41.86 });
            transaction.Lines.Add(new TransactionLine() { Account = "CATEGORY1", Type = "CATEGORY", Amount = 41.86 });
            this.DataContext = transaction;

        }

    }

    public class Transaction
    {
        public Transaction()
        {
            this.Lines = new ObservableCollection<TransactionLine>();
        }
        public DateTime Date { get; set; }
        public string Payee { get; set; }
        public ObservableCollection<TransactionLine> Lines { get; set; }
    }
    public class TransactionLine : INotifyPropertyChanged, IEditableObject
    {

        void IEditableObject.BeginEdit()
        {

        }
        void IEditableObject.CancelEdit()
        {

        }
        void IEditableObject.EndEdit()
        {

        }

        public TransactionLine() { }

        private string _account;
        private string _type;
        private double _amount;

        public string Account
        {
            get
            {
                return this._account;
            }
            set
            {
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Account"));
                this._account = value;
            }
        }
        public string Type
        {
            get
            {
                return this._type;
            }
            set
            {
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Type"));
                this._type = value;
            }
        }
        public double Amount
        {
            get
            {
                return this._amount;
            }
            set
            {
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Amount"));
                this._amount = value;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

    }

    public class Converter1 : IValueConverter
    {

        object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Math.Round(((CollectionViewGroup)value).Items.Sum(l => ((TransactionLine)l).Amount), 2);
        }
        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

    }

}

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Проблема здесь в том, что конвертер вызывается только при установленном свойстве databound.А поскольку вы привязываетесь к самому CollectionViewGroup, метод Convert не будет вызываться при добавлении нового элемента в ObservableCollection<TransactionLine>.

Вместо привязки к самой CollectionViewGroup, вы можете использовать реализацию MultiBinding и IMultiValueConverter для привязки к свойству Count исходной коллекции:

public class Converter1 : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return Math.Round(((CollectionViewGroup)values[0]).Items.Sum(l => ((TransactionLine)l).Amount), 2);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML:

<ControlTemplate TargetType="GroupItem">
    <StackPanel>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0" Content="{Binding Path=Name}" Padding="0"/>
            <Label Grid.Column="1" Padding="0">
                <Label.Content>
                    <MultiBinding Converter="{StaticResource c1}">
                        <Binding Path="."  />
                        <Binding Path="Items.Count" />
                    </MultiBinding>
                </Label.Content>
            </Label>
        </Grid>
        <ItemsPresenter/>
    </StackPanel>
</ControlTemplate>
0 голосов
/ 27 декабря 2018

Вы вызываете событие PropertyChanged перед тем, как назначить новое значение вспомогательному полю.Убедитесь, что вы вызываете его после назначения value для своего поля.

public string Account
{
    get
    {
        return this._account;
    }
    set
    {
        this._account = value;
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Account"));
    }
}
...