簡體   English   中英

WPF DataGrid列總MVVM模式

[英]WPF DataGrid Column Total MVVM Patern

我在DataGrid中有一列是Price字段。 在表單底部的TextBlock中。

如何基於Price列的值在TextBlock顯示總值?

XAML代碼:

 <Grid>
    <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding Path=SaleryDetailsCollection, Mode=TwoWay}" AutoGenerateColumns="False" VerticalAlignment="Top" Width="640" Height="192" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Type" Binding="{Binding Type, Mode=TwoWay, NotifyOnTargetUpdated=True, ValidatesOnDataErrors=True}" Width="*" />
            <DataGridTextColumn Header="Amount" Binding="{Binding Price, Mode=TwoWay, NotifyOnTargetUpdated=True, ValidatesOnDataErrors=True}" Width="*" />
        </DataGrid.Columns>
    </DataGrid>
    <TextBlock HorizontalAlignment="Left" Margin="415,358,0,0" TextWrapping="Wrap" Text="{Binding SalaryTotal}" VerticalAlignment="Top"/>
</Grid>

視圖模型:

public ObservableCollection<SaleryDetailsModel> SaleryDetailsCollection
{
    get { return _SaleryDetailsCollection; }
    set
    {
        SalaryTotal = SaleryDetailsCollection.Sum(x => x.Amount);
        _SaleryDetailsCollection = value;
        NotifyPropertyChanged("SaleryDetailsCollection");
    }
}
public Double SalaryTotal
{
    get { return _SalaryTotal; }
    set
    {
        _SalaryTotal = value;
        NotifyPropertyChanged("SalaryTotal");
    }
}

類SaleryDetailsMode

  class SaleryDetailsModel:ViewModel
{
    private Double _Amount;
    private String _Type;
    public Double Amount
    {
        get { return _Amount; }
        set
        {
            _Amount = value;
            NotifyPropertyChanged("Amount");
        }
    }
    public String Type { get { return _Type; } set { _Type = value; NotifyPropertyChanged("Type"); } }

}

類ViewModel

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

將此代碼添加到構造函數中

SaleryDetailsCollection = new ObservableCollection<SaleryDetailsModel>();
SaleryDetailsCollection.CollectionChanged += MyItemsSource_CollectionChanged;

在ViewModel中

void MyItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
            foreach (SaleryDetailsModel item in e.NewItems)
                item.PropertyChanged += MyType_PropertyChanged;

        if (e.OldItems != null)
            foreach (SaleryDetailsModel item in e.OldItems)
                item.PropertyChanged -= MyType_PropertyChanged;
    }

void MyType_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Amount")
            DoWork();
    }

    private void DoWork()
    {
        SalaryTotal = SaleryDetailsCollection.Sum(x => x.Amount);
    }

XAML

<Grid>
<DataGrid HorizontalAlignment="Left" ItemsSource="{Binding Path=SaleryDetailsCollection, Mode=TwoWay}" AutoGenerateColumns="False" VerticalAlignment="Top" Width="640" Height="192" >
    <DataGrid.Columns>
        <DataGridTextColumn Header="Type" Binding="{Binding Type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="*" />
        <DataGridTextColumn Header="Amount" Binding="{Binding Price, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="*" />
    </DataGrid.Columns>
</DataGrid>
<TextBlock HorizontalAlignment="Left" Margin="415,358,0,0" TextWrapping="Wrap" Text="{Binding SalaryTotal}" VerticalAlignment="Top"/>

必須在分配字段之后進行計算:

public ObservableCollection<SaleryDetailsModel> SaleryDetailsCollection
{
    get { return _SaleryDetailsCollection; }
    set
    {
        _SaleryDetailsCollection = value;
        SalaryTotal = SaleryDetailsCollection.Sum(x => x.Amount); // This line must be after the field assignment.
        NotifyPropertyChanged("SaleryDetailsCollection");
    }
}

您需要使用一個集合,該集合將在其屬性更改時得到通知。 請參閱鏈接https://social.msdn.microsoft.com/Forums/silverlight/en-US/12915e07-be95-4fc5-b8f0-b0a49b10bc57/observablecollection-item-changed 它具有NotifyableCollection。 我已將其用於以下代碼。

<Grid>
    <StackPanel>
        <DataGrid x:Name="dgr" HorizontalAlignment="Left" ItemsSource="{Binding Path=Salaries, Mode=TwoWay}"
                  AutoGenerateColumns="True" VerticalAlignment="Top" Width="640" Height="192" >                
        </DataGrid>
        <TextBlock HorizontalAlignment="Left"  TextWrapping="Wrap"  VerticalAlignment="Top" Text="{Binding TotalSalary}">               
        </TextBlock>
    </StackPanel>
</Grid>

 class ViewModel : INotifyPropertyChanged
{
    private NotifiableCollection<Salary> salaries;        
    double _totalSal;
    public double TotalSalary
    {
        get { return _totalSal = Salaries.Sum(x => x.Amount); }
        set { _totalSal = value; }
    }

    public NotifiableCollection<Salary> Salaries
    {
        get { return salaries; }
        set
        {
            salaries = value;
            if (salaries != null)
            {
                salaries.ItemChanged += salaries_ItemChanged;
            }

        }
    }

    void salaries_ItemChanged(object sender, NotifyCollectionChangeEventArgs e)
    {
        OnPropertyChanged("TotalSalary");
    }     


    public ViewModel()
    {
        Salaries = new NotifiableCollection<Salary>();
        for (int i = 0; i < 10; i++)
        {
            Salary s = new Salary() { Type="Type"+i,Amount=new Random().Next(20000,30000)};

            Salaries.Add(s);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }

}


class Salary : INotifyPropertyChanged
{
    private string type;

    public string Type
    {
        get { return type; }
        set { type = value; OnPropertyChanged("Type"); }
    }
    private double amount;

    public double Amount
    {
        get { return amount; }
        set { amount = value; OnPropertyChanged("Amount"); }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

public class NotifyCollectionChangeEventArgs : PropertyChangedEventArgs
    {
        public int Index { get; set; }
        public NotifyCollectionChangeEventArgs(int index, string propertyName) : base(propertyName) { Index = index; }
    }

public class NotifiableCollection<T> : ObservableCollection<T> where T : class, INotifyPropertyChanged
{
    public event EventHandler<NotifyCollectionChangeEventArgs> ItemChanged;

    protected override void ClearItems()
    {
        foreach (var item in this.Items)
            item.PropertyChanged -= ItemPropertyChanged;
        base.ClearItems();
    }

    protected override void SetItem(int index, T item)
    {
        this.Items[index].PropertyChanged -= ItemPropertyChanged;
        base.SetItem(index, item);
        this.Items[index].PropertyChanged += ItemPropertyChanged;
    }

    protected override void RemoveItem(int index)
    {
        this.Items[index].PropertyChanged -= ItemPropertyChanged;
        base.RemoveItem(index);
    }

    protected override void InsertItem(int index, T item)
    {
        base.InsertItem(index, item);
        item.PropertyChanged += ItemPropertyChanged;
    }

    private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        T changedItem = sender as T;
        OnItemChanged(this.IndexOf(changedItem), e.PropertyName);
    }

    private void OnItemChanged(int index, string propertyName)
    {
        if (ItemChanged != null)
            this.ItemChanged(this, new NotifyCollectionChangeEventArgs(index, propertyName));
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM