簡體   English   中英

WPF綁定where子句可能嗎?

[英]WPF binding with where clause possible?

如果我有一個像這樣的Observable集合:

public ObservableCollection<SpecialPriceRow> SpecialPriceRows = new ObservableCollection<SpecialPriceRow>();

SpecialPriceRow類:

public class SpecialPriceRow : INotifyPropertyChanged
{
    public enum ChangeStatus
    {
        Original,
        Added,
        ToDelete,
        Edited
    }

    public ChangeStatus Status { get; set; }
    public string PartNo { get; set; }

    private decimal _price;
    public decimal Price
    {
        get
        {
            return _price;
        }
        set
        {
            if (value != _price)
            {
                _price = value;
                Status = ChangeStatus.Edited;
                OnPropertyChanged("Status");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

我是否可以將XAML中的Label綁定到說...添加的對象計數? 所以我可以得到這樣的東西:

在此處輸入圖片說明

綠色是集合中“已添加”對象的計數。 我將如何做這樣的事情?

我不知道有任何內置功能可以做到這一點。 我將在您的數據上下文類中創建一個自定義屬性來進行計數並綁定到此。

像這樣:

public int AddedCount
{
    get
    {
        return SpecialPriceRows.Where(r => r.Status == ChangeStatus.Added).Count();
    }
}

然后,無論何時更改或添加項目,您都需要顯式提高為此更改的屬性:

public void AddItem()
{
    ...
    OnPropertyChanged("AddedCount");
}

然后,您只需要像這樣綁定XAML代碼:

<TextBlock Text="{Binding AddedCount}" />

您可能需要訂閱集合中的change事件,以了解項目何時更改。

選擇:

您還可以創建帶有特定過濾器的ListCollectionView並綁定到其Count屬性:

    AddedItems = new ListCollectionView(TestItems);
    AddedItems.Filter = r => ((SpecialPriceRow)r).Status == ChangeStatus.Added;

然后,在XAML中,您將綁定到此的Count屬性:

<TextBlock Text="{Binding AddedItems.Count}" />

這樣做的好處是,它將自動跟蹤集合中已添加和已刪除項目,並自行更新。 盡管當項目的屬性更改會影響過濾器時,您仍必須手動刷新它。

我已經編寫了一個ViewModel,它將執行您正在尋找的所需功能。

    class VM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public ObservableCollection<SpecialPriceRow> _SpecialPriceRows = new ObservableCollection<SpecialPriceRow>();
        private int _Original = 0;
        private int _Added = 0;
        private int _ToDelete = 0;
        private int _Edited = 0;

        public VM()
        {
            PropertyChanged = new PropertyChangedEventHandler(VM_PropertyChanged);

            //The following lines in the constructor just initialize the SpecialPriceRows.
            //The important thing to take away from this is setting the PropertyChangedEventHandler to point to the UpdateStatuses() function.
            for (int i = 0; i < 12; i++)
            {
                SpecialPriceRow s = new SpecialPriceRow();
                s.PropertyChanged += new PropertyChangedEventHandler(SpecialPriceRow_PropertyChanged);
                SpecialPriceRows.Add(s);
            }
            for (int j = 0; j < 12; j+=2)
                SpecialPriceRows[j].Price = 20;
        }

        private void VM_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
        }

        private void SpecialPriceRow_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Status")
                UpdateStatuses();
        }

        public ObservableCollection<SpecialPriceRow> SpecialPriceRows
        {
            get
            {
                return _SpecialPriceRows;
            }
        }

        private void UpdateStatuses()
        {
            int original = 0, added = 0, todelete = 0, edited = 0;
            foreach (SpecialPriceRow SPR in SpecialPriceRows)
            {
                switch (SPR.Status)
                {
                    case SpecialPriceRow.ChangeStatus.Original:
                        original++;
                        break;
                    case SpecialPriceRow.ChangeStatus.Added:
                        added++;
                        break;
                    case SpecialPriceRow.ChangeStatus.ToDelete:
                        todelete++;
                        break;
                    case SpecialPriceRow.ChangeStatus.Edited:
                        edited++;
                        break;
                    default:
                        break;
                }
            }
            Original = original;
            Added = added;
            ToDelete = todelete;
            Edited = edited;
        }

        public int Original
        {
            get
            {
                return _Original;
            }
            set
            {
                _Original = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Original"));
            }
        }

        public int Added
        {
            get
            {
                return _Added;
            }
            set
            {
                _Added = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Added"));
            }
        }

        public int ToDelete
        {
            get
            {
                return _ToDelete;
            }
            set
            {
                _ToDelete = value;
                PropertyChanged(this, new PropertyChangedEventArgs("ToDelete"));
            }
        }

        public int Edited
        {
            get
            {
                return _Edited;
            }
            set
            {
                _Edited = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Edited"));
            }
        }
    }

注意構造函數中的注釋。 您需要將每個SpecialPriceRow的PropertyChanged事件指向UpdateStatuses函數,以使其正常工作。 現在,您需要做的就是將標簽綁定到ViewModel中的適當屬性。 如果您的SpecialPriceRows列表變得非常大,則您可能需要考慮以不同的方式計算狀態計數。 當前,每次更新一個實例時,它都會遍歷整個列表。 為了更好地執行此操作,您可能希望將狀態的舊值保留在SpecialPriceRow類中,並且每次進行更新時,增加新的狀態數並減少舊的狀態數。

暫無
暫無

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

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