今天再試了一下,
用原程式碼 https://pastebin.com/GEJ5yMWd ,
改兩個地方能夠做到更新:
1. 在addItem_Click加上Refresh的動作:
private void addItem_Click(object sender, RoutedEventArgs e)
{
//有增加進去, 但是UI不會新增這一筆1983的資料
Employees.Add(new Employee
{
FirstName = "FirstName10",
LastName = "LastName10",
HireDate = new DateTime(1983, 1, 1)
});
var s =
((CollectionViewSource)this.FindResource("EmployeesSource"));
s.View.Refresh();
}
2. 以及將 EmployeeCollectionView改寫為:
class EmployeeCollectionView : ListCollectionView
{
private readonly IEnumerable<EmployeeCollectionViewGroup> _groups;
public override ReadOnlyObservableCollection<object> Groups
{
get { return new ReadOnlyObservableCollection<object>(new
ObservableCollection<object>(_groups)); }
}
public EmployeeCollectionView(IList list)
: base(list)
{
_groups = list
.OfType<Employee>()
.GroupBy(x => x.HireDate)
.Select(x => new EmployeeCollectionViewGroup(x.Key, x));
}
}
測試可以有更新UI的效果
更改說明:
我後來試了一下,UI上員工分群資料實際上是取用EmployeeCollectionView的Groups,
而如果要更新UI,在集合變動的時候,
應該至少會引發Groups的get動作,
但是原程式碼下中斷點在get,當按下add按鈕不會引發get
我觀察一般的Binding,
WPF在集合有變動時會自動內部幫你再引發get一次
不過我猜自定義CollectionView時不知少了什麼東西,所以這個重get機制沒辦法運作
目前只找到第一點主動Refresh的方式讓他引發get
可以引發get後,原程式碼的寫法
public EmployeeCollectionView(IList list)
: base(list)
{
_groups = list
.OfType<Employee>()
.GroupBy(x => x.HireDate)
.Select(x => new EmployeeCollectionViewGroup(x.Key, x))
.ToList();
這邊建構式會把Source綁定的Employees傳進來,
但最後的ToList應有產生一個新List的效果,
因此_groups變成取產生的新List而不是Employees的參考,
導致Employees變動時,_groups的值不會跟著變動
上方第二點改寫去掉ToList,讓_groups保持取得Employees的參考並分組的集合,
在get時相當於將變動後的Employees分組回傳,就能反映出Employees的變動到UI上
不知這樣做法如何
(目前還不知道如何不透過Refresh就可以在集合變動時讓他重Get)
補充1:
剛想到一個更簡潔的方式,
可以把Refresh的動作加到Employees.CollectionChanged,
其他地方只需對集合做增刪即可引發CollectionChanged的Refresh,
不需重複寫Refresh
在建構式寫上
public Window2()
{
InitializeComponent();
//初始化這邊可以加到UI上
Employees = new ObservableCollection<Employee>
{
new Employee { FirstName = "FirstName1", LastName =
"LastName1", HireDate = new DateTime(1970, 1, 1) },
........
};
Employees.CollectionChanged += Employees_CollectionChanged;
DataContext = this;
}
及 Employees_CollectionChanged:
private void Employees_CollectionChanged
(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
((CollectionViewSource)this.FindResource("EmployeesSource")).View.Refresh();
}
: : 各位好,
: : 我有資料需要分組, 所以我用了listbox 搭配CollectionViewSource的group去分類
: : group heaer的layout有一個delete的image可以刪除整個group
: : 但是現在有需求是如果目前正在刪除中,
: : 這個delete image要把他disable 或是 隱藏起來
: : 所以我在delete image的tag屬性讓它bing住group item本身,
: : 這樣我在delete image 按下時可以拿到group item的datacontext是CollectionViewGroup
: : 所以我想客製化CollectionViewGroup, 多加一個屬性進去CollectionViewGroup去控制
: : delete image的visibility
: : 找到網路上有人做類似的客製化
: : 但我目前遇到如果我動態增加一筆資料時, UI就不會更新,
: : 不知道是哪邊漏了實作, 希望有人幫我解答或是什麼關鍵字可以找到資料, 謝謝各位
: : 程式碼
: : https://pastebin.com/GEJ5yMWd