WPF - привязка получить свойство - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть DataGrid с формой, и я хотел бы уведомить другое свойство get. Вот мой пример:

ViewModel

public ObservableCollection<Data> Data
{
   get => _data;
   set {
     _data = value;
     OnPropertyChanged(nameof(Data));
   }
}

public int Summary => Data.Sum(data => data.Number);

XAML

  <DataGrid ItemsSource="{Binding Data}">
    ...
     <TextBox Title="{Binding Number, UpdateSourceTrigger=PropertyChanged"/>
    ...
  </DataGrid>

<StackPanel>
  <Label Content="Summary: "/>
  <TextBlock Text="{Binding Summary}"/>
</StackPanel>

Когда я записываю число в сетку данных, Summary по-прежнему равен 0. Как уведомить свойство Summary, когда я изменяю значение в коллекции? Спасибо

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Возможно, проще использовать BindingList. У него есть событие ListChanged, которое возникает, если

  • один из его предметов поднимает себя PropertyChanged событие
  • пункт был добавлен
  • предмет был удален
  • предмет был перемещен

Он даст вам информацию о том, какое изменение было обнаружено (ListChangedType) и где в списке произошло изменение (NewIndex и OldIndex). Это решение подразумевает, что ваш Data класс также реализует INotifyPropertyChanged

Это будет означать следующие изменения в вашей viewmodel

// if you do not change the list object, there is no need to raise PropertyChanged in setter
public BindingList<Data> Data { get; set; } = new BindingList<Data>();

// constructor
public ViewModel(){
    // Update property Summary if our list changes.
    List.ListChanged += (sender, arg) => OnPropertyChanged(nameof(Summary));
}
0 голосов
/ 18 сентября 2018

Проверьте это: https://www.codeproject.com/Tips/694370/How-to-Listen-to-Property-Chang

Что вам нужно, так это уведомление о любых изменениях в Коллекции.

Обновление:

Скажите, данные, которые появятся в сетке:

public class Data
{
    public string Name { get; set; }
    private int _Salary;
    public int Salary
    {
        get
        {
            return _Salary;
        }
        set
        {
            _Salary = value;
            SalaryChanged?.Invoke();
        }
    }

    public Action SalaryChanged { get; set; }
}

Вместо ObservableCollection - используйте это:

public class ObsCollection : ObservableCollection<Data>
{
    private Action SalaryChanged;
    public ObsCollection(Action NotifyPropertyChanged)
    {
        SalaryChanged = NotifyPropertyChanged;
    }

    protected override void InsertItem(int index, Data item)
    {
        item.SalaryChanged = SalaryChanged;
        base.InsertItem(index, item);
    }

    protected override void RemoveItem(int index)
    {            
        base.RemoveItem(index);
        SalaryChanged?.Invoke();
    }

    protected override void ClearItems()
    {
        base.ClearItems();
        SalaryChanged?.Invoke();
    }
}

Наконец - в модели View

public class MainWindowVM : INotifyPropertyChanged
{
    private ObsCollection _Data = null;

    public ObsCollection Data
    {
        get
        {
            return _Data;
        }
        set
        {
            _Data = value;
        }
    }

    public int TotalSalary
    {
        get
        {
            return _Data.Sum(d => d.Salary);
        }
    }

    public MainWindowVM()
    {
        _Data = new ObsCollection(NotifyTotalSalaryChanged);
        LoadData();
    }

    public void LoadData()
    {
        _Data.Add(new Data { Name = "Test1", Salary = 1000 });
        _Data.Add(new Data { Name = "Test2", Salary = 2000 });
        _Data.Add(new Data { Name = "Test3", Salary = 3000 });
        Notify("Data");
    }

    private void NotifyTotalSalaryChanged()
    {
        Notify("TotalSalary");
    }

    #region Property Changed Stuff
    public event PropertyChangedEventHandler PropertyChanged;

    public void Notify(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}

============================================= Xaml просто:

<Window x:Class="CstomObserve.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:CstomObserve"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
    <local:MainWindowVM/>
</Window.DataContext>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <DataGrid Grid.Row="0" ItemsSource="{Binding Data, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Grid.Row="1" Text="{Binding TotalSalary, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...