我有一個帶有 ObservableCollection 的 ListView。用戶類有一個包含組的串列。我有另一個 ListView 顯示所選用戶的組。現在我嘗試添加/洗掉組,但它們不會實時重繪 。如果我選擇另一個用戶并回傳我的用戶,我會看到更新的串列。
XAML:
<ListView ItemsSource="{Binding ListUsers}" SelectedItem="{Binding SelectedUser}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
[...]
<ListView ItemsSource="{Binding SelectedUser.Groups}" SelectedItem="{Binding SelectedGroup}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
班級:
public class User : ObservableObject
{
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
private ObservableCollection<string> groups;
public ObservableCollection<string> Groups
{
get => groups;
set => SetProperty(ref groups, value);
}
}
視圖模型:
private ObservableCollection<User> listusers;
public ObservableCollection<User> ListUsers
{
get => listusers;
private set => SetProperty(ref listusers, value);
}
private User _selectedUser;
public User SelectedUser
{
get => _selectedUser;
set => SetProperty(ref _selectedUser, value);
}
private string _selectedGroup;
public string SelectedGroup
{
get => _selectedGroup;
set => SetProperty(ref _selectedGroup, value);
}
public async Task DelGroup()
{
await Task.Run(() =>
{
//SelectedUser.Groups.Remove(SelectedGroup);
for (int i = 0; i < ListUsers.Count; i )
{
if (SelectedUser.SAMAccountName == ListUsers[i].SAMAccountName)
{
ListUsers[i].Groups.Remove(SelectedGroup);
}
}
});
}
uj5u.com熱心網友回復:
僅使用后臺執行緒將作業轉移到Dispatcher性能不佳的結果中,應避免使用。充其量,性能與使用您的代碼直接在 UI 執行緒上洗掉組時的性能相同。這意味著沒有改進。
如果您創建并維護一個查找表,其中是鍵,值是其項SAMAccountName的集合(以防您的表不允許重復鍵),您將獲得最佳性能:UserSAMAccountName
public ObservableCollection<User> ListUsers { get; }
private Dictionary<string, IList<User>> UserTable { get; }
public ViewModel()
{
this.ListUsers = new ObservableCollection<User>();
this.ListUsers.ColectionChanged = OnUsersChanged;
}
public void DelGroup()
{
if (!this.UserTable.TryGetValue(this.SelectedUser.SAMAccountName, out IList<User>> usersWithEqualName)
{
return;
}
foreach (var user in usersWithEqualName)
{
user.Group.Remove(this.SelectedGroup);
}
}
private void OnUsersChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var newUser in e.NewItems.Cast<User>())
{
AddUserToLookupTable(newUser);
}
break;
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Replace:
foreach (var oldUser in e.OldItems.Cast<User>())
{
RemoveUserFromLookupTable(oldUser);
}
break;
case NotifyCollectionChangedAction.Reset:
this.UserTable.Clear();
break;
}
}
private void AddUserToLookupTable(User user)
{
if (!this.UserTable.TryGetValue(user.SAMAccountName, out IList<User>> usersWithEqualName)
{
usersWithEqualName = new List<User>();
this.UserTable.Add(user.SAMAccountName, usersWithEqualName);
}
usersWithEqualName.Add(user);
}
private void RemoveUserFromLookupTable(User user)
{
if (!this.UserTable.TryGetValue(user.SAMAccountName, out IList<User>> usersWithEqualName)
{
return;
}
usersWithEqualName.Remove(user);
if (!usersWithEqualName.Any())
{
this.UserTable.Remove(user.SAMAccountName);
}
}
一個更簡單的解決方案是確保所有實體User.Group都是相同User的實體。這樣,從一個User.Group集合中洗掉一個組,將從所有集合中洗掉它。這將消除上述解決方案,甚至表現得更好。但是這個解決方案只有在所有User實體都具有相同組的情況下才可行。
uj5u.com熱心網友回復:
找到答案了……我太傻了。
Application.Current.Dispatcher.Invoke(() => SelectedUser.Groups.Remove(SelectedGroup));
uj5u.com熱心網友回復:
您需要通過調度程式呼叫操作,因為您從 ThreadPool 執行緒啟動它 - 使用 Task.Run。
如果您重寫,您可以放棄 Dispatcher 呼叫并仍然受益于非阻塞 asyc 呼叫,以便修改 UIElement 訪問發生在主執行緒上。
例如像:
public async Task DelGroup()
{
foreach (int index in await Task.Run(GetRemoveIndices).ConfigureAwait(true)) {
ListUsers[index].Groups.Remove(SelectedGroup);
};
IEnumerable<int> GetRemoveIndices() {
for (int i = ListUsers.Count-1; i >= 0; i--) {
if (SelectedUser.SAMAccountName == ListUsers[i].SAMAccountName) {
yield return i;
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/472750.html
上一篇:當我嘗試從Array物件呼叫IList介面中的洗掉方法時,無法識別它
下一篇:c#.Last的替代品
