我有非常大的網格。我想使用複選框「檢查/取消全選」,這將檢查/取消選中所有行。但它很慢,因爲有很多OnPtopertyChanged事件的調用。我如何才能引發OnPropertyChanged事件只爲可見元素?行的虛擬化已啓用。如何僅爲可見元素引發OnPropertyChanged?
回答
第一種方法:取出OnPropertyChanged的認識和添加dataGrid.Items.Refresh();
第二種方法:在後臺更改屬性,然後
var rows = grid.FindChildren<DataGridRowsPresenter>().First() as DependencyObject;
int count = VisualTreeHelper.GetChildrenCount(rows);
for (int i = 0; i < count; i++)
{
DataGridRow row = VisualTreeHelper.GetChild(rows, i) as DataGridRow;
(row.DataContext as IViewModel).Refresh();//Refresh invokes OnPropertyChanged
}
處理此問題的一種方法是在ViewModel中具有boolean IsVisible
屬性。如果IsVisible
只返回true
,那麼您可以提高PropertyChanged
事件。
唯一的問題是如何爲虛擬網格設置這些IsVisible標誌:) – 2011-12-22 09:25:49
我的意思是說你的MV :) – 2011-12-22 09:39:35
20000行很多:)
如果斷開的ItemsSource綁定改變你的列表視圖模型的和的ItemsSource設置爲新的檢查清單會發生什麼?如果他們想20000rows他們可以等待它
oterwise;)
編輯
如果你不改變你的ItemsSource你必須提高的PropertyChanged對每一個項目,否則你沒有看到的變化。
另一種方式是設置綁定爲空或新的列表
this.MyGridItemsViewModelProperty = new List();//"disconnect" the binding to the grid for the all check/uncheck
然後改變你與選中/清除實時列表,並把它設回爲網格的ItemsSource
this.MyGridItemsViewModelProperty = myupdatelist;
電網
<Grid ItemsSource="{Binding MyGridItemsViewModelProperty}" />
但我不知道如果第二種方法更快,你應該測試它。
我該如何斷開連接然後連接相同的DataSource?它只刷新隱藏的元素。但它工作得更快。 – Rover 2011-12-22 10:18:41
你寫的check/unckeck是非常慢的 - 現在你寫的非常快?真正的問題是什麼?也許你應該發佈你的datagrid綁定xaml,觸發器和你的viewmodel。 – blindmeis 2011-12-22 10:30:38
問題出在OnPropertyChanged上。如果我在每個元素的每個檢查上調用它,它的工作速度會很慢。我刪除它,它運行得很快,但UI不顯示更改。所以,我只需要刷新UI的可見部分。 – Rover 2011-12-22 10:33:52
更新1我創建了一個具有100K行的簡單repro,並在我的低規格PC上飛行,您可以檢查一下它並確認它是否足夠快?項目名稱GroupSelect
然後只是複製/過去的東西到主窗口。
代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace GroupSelect
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded +=
(o, e) =>
{
this.DataContext =
new Model(100000);
};
}
}
public class Model : INotifyPropertyChanged
{
private bool? isAllSelected = null;
public Model(int itemCount)
{
this.Items =
Enumerable.Range(1, itemCount).Select(t =>
new Item(this)
{
Name = "n_" + t.ToString()
}).ToList();
this.IsAllSelected = false;
}
public List<Item> Items
{
get;
private set;
}
public bool? IsAllSelected
{
get
{
return this.isAllSelected;
}
set
{
if (this.IsAllSelected != value)
{
this.IsBatchUpdate = true; // updating
this.isAllSelected = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this,
new PropertyChangedEventArgs("IsAllSelected"));
}
//
if (this.IsAllSelected.HasValue)
{
foreach (Item i in this.Items)
{
i.IsSelected = value.Value;
}
}
this.IsBatchUpdate = false; // updating
}
}
}
public bool IsBatchUpdate
{
get;
private set;
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Item: INotifyPropertyChanged
{
private bool isSelected = false;
public Item(Model model)
{
this.Model = model;
}
public Model Model
{
get;
private set;
}
public string Name
{
get;
set;
}
public bool IsSelected
{
get
{
return this.isSelected;
}
set
{
if (this.IsSelected != value)
{
this.isSelected = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this,
new PropertyChangedEventArgs("IsSelected"));
}
if (!this.Model.IsBatchUpdate)
{
this.Model.IsAllSelected = null;
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
標記:
<Window x:Class="GroupSelect.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GroupSelect"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="g" AutoGenerateColumns="False"
ItemsSource="{Binding Path='Items'}">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}">
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate>
<CheckBox HorizontalAlignment="Center"
DataContext="{Binding Path=DataContext,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
IsChecked="{Binding Path=IsAllSelected, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
問題是,所有集合都發生更改的通知不會生效,而我根本不會更改它。 grid.ItemsSource = null; grid.ItemsSource = elements; - 它不適用於可見行,但會影響滾動下的元素。此外,RaisePropertyChanged((()=> Elements)不起作用。 – Rover 2011-12-22 10:29:56
請找到更新的解決方案。 – 2011-12-22 11:32:58
- 1. 如何僅考慮可見元素來獲取當前元素的索引?
- 2. 如何僅在特定元素可見時觸發事件
- 3. Ember.js QUnit僅測試可見元素find()
- 4. 元素僅在特定高度可見
- 5. 索引/匹配僅可見單元格
- 6. 如何僅在前面的元素可見時纔有餘量?
- 7. 如何僅驗證表單的可見元素?
- 8. 如何僅將n-child或n-type應用於可見元素?
- 9. 如何僅在元素可見的情況下執行邏輯
- 10. WPF控制可見性w/ICommand&OnPropertyChanged
- 11. 元素不可見
- 12. 元素不可見
- 13. 如何raphael.serialize只有可見的元素?
- 14. 如何「清除」溢出:可見元素?
- 15. 如何檢查元素可見
- 16. 如何僅爲可見單元格應用條件格式?
- 17. JQuery將隱藏元素檢測爲可見和可見元素隱藏
- 18. ASP使不可見元素可見
- 19. 硒可見,非可見元素(下拉)
- 20. 如何觸發一個元素淡入當一個元素可見時首先?
- 21. 行爲不觸發OnPropertyChanged
- 22. 如何在元素中只顯示:: after僞元素可見?
- 23. 將元素從變爲可見(而不是從不可見)
- 24. 硒可見元素不會被識別爲可見
- 25. 如何僅爲img元素設置類?
- 26. Rails窗體 - 僅提交可見元素(具有相同ID的2x元素)
- 27. 元素是否可見?
- 28. WebdriverJS ElementNotVisibleError:元素不可見
- 29. org.openqa.selenium.ElementNotVisibleException:元素不可見
- 30. 元素不可見Selenium
您在這裏挑戰WPF的基礎知識。沒有簡單的方法做到這一點。你有沒有考慮使用分頁? – 2011-12-22 09:36:49
分頁可能會混淆的是「全部檢查」檢查所有頁面上的所有元素或僅在當前頁面上。 – Rover 2011-12-22 09:41:00
如何設置檢查/取消選中所有行?請發佈此代碼 – blindmeis 2011-12-22 09:41:58