Dzień dobry,
Mam w aplikacji (MVVM) DataGrid z dość dużą ilością rekordów (około 2600). Rekord posiada zbindowany parametr 'Visibility', który warunkuje jego widoczność. Jeżeli szukana fraza (wpisywana do TextBoksa) znajduje się w kolekcji to parametr ma wartość 'Visible', a jeżeli nie to 'Collapsed'. Dzięki temu realizuję wyszukiwanie w takim DataGridzie.
Teraz o co chodzi... Rekordy po włączeniu okna ładują się bardzo szybko i ładnie się przewijają. DataGrid jest zwirtualizowany i posiada parametr 'ScrollViewer.CanContentScroll' ustawiony na True.
Oto kilka pierwszych rekodrów załadowanej w całości kolekcji:
A teraz coś czego nie umiem naprawić. Kiedy wpiszę frazę wyszukiwania i program skończy szukać pojawia się taki oto efekt:
Ponad to scrollowanie pionowe chodzi wtedy niesamowicie wolno.
Tutaj jest kod formatek ze screenów:
<TabControl Grid.Row="3" Grid.Column="0" Margin="0,0,5,0">
<TabItem>
<TabItem.Header>
<Label Content="Dodaj towar:" Padding="0" FontWeight="Bold"/>
</TabItem.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Label Content="Nazwa:" Grid.Row="0" Grid.Column="0"
VerticalContentAlignment="Center" Margin="2"/>
<TextBox Grid.Row="0" Grid.Column="1" Margin="2"
VerticalContentAlignment="Center"
Text="{Binding DTM_dodawanyTowar,UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding znajdzTowar}"/>
</TextBox.InputBindings>
</TextBox>
<Button Grid.Row="0" Grid.Column="2" Margin="2"
Content="Dodaj" Width="60"
Command="{Binding dodajTowar}"/>
</Grid>
</TabItem>
</TabControl>
<TabControl Grid.Row="4" Grid.Column="0" Margin="0,5,5,0">
<TabItem>
<TabItem.Header>
<Label Content="Lista towarów:" Padding="0" FontWeight="Bold"/>
</TabItem.Header>
<DataGrid VerticalGridLinesBrush="Silver" HorizontalGridLinesBrush="Silver"
AutoGenerateColumns="False" HeadersVisibility="Column"
CanUserAddRows="False"
ItemsSource="{Binding OCTM_listaTowarow,UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding TM_wybranyTowar,UpdateSourceTrigger=PropertyChanged}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Single"
EnableRowVirtualization="True"
EnableColumnVirtualization="True">
<!-- Styl nagłówka kolumn -->
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGrid.ColumnHeaderStyle>
<!-- Styl wiersza Tutaj jest warunek widoczności wiersza -->
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightYellow"/>
<Setter Property="BorderBrush" Value="LightYellow"/>
</Trigger>
</Style.Triggers>
<Setter Property="Visibility" Value="{Binding widocznosc,UpdateSourceTrigger=PropertyChanged}"/>
</Style>
</DataGrid.CellStyle>
<!-- Kolumny -->
<DataGrid.Columns>
<!-- Lp. -->
<DataGridTemplateColumn Header="Lp.">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label FontSize="12" Margin="3" HorizontalAlignment="Center"
VerticalAlignment="Center" Padding="0"
Content="{Binding lp,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- Nazwa -->
<DataGridTemplateColumn Header="Nazwa" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Label FontSize="12" Margin="3" HorizontalAlignment="Left"
VerticalAlignment="Center" Padding="0"
Grid.Row="0" Grid.Column="0" Content="{Binding nazwa,UpdateSourceTrigger=PropertyChanged}"/>
<StackPanel Orientation="Horizontal"
Grid.Row="0" Grid.Column="1">
<Button Width="25" Margin="2" ToolTip="Usuń"
Command="{Binding DataContext.usunTowar,
RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"
IsEnabled="{Binding czyNieJestSkladowa,UpdateSourceTrigger=PropertyChanged}">
<Image Source="/Zapotrzebowanie stali;component/Icons/usun.png" Width="14"/>
</Button>
<Button Width="25" Margin="2" ToolTip="Zmień"
Command="{Binding DataContext.modyfikujTowar,
RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}">
<Image Source="/Zapotrzebowanie stali;component/Icons/zmien.png" Width="14"/>
</Button>
</StackPanel>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</TabItem>
</TabControl>
Kiedy ustawię parametr DataGrid ScrollViewer.CanContentScroll na False wszystko chodzi bardzo płynnie (wyszukiwanie i przewijanie) ale ładowanie danych trwa potwornie długo. Dodatkowo problem rekordów po wyszukiwaniu (taki jak na drugim screenie) w ogóle nie występuje i DataGrid działa dobrze.
Dane ładuję w ten sposób:
this.OCTM_listaTowarow to obiekt typu ObservableCollection<TowarModel> gdzie TowarModel to klasa zawierająca pola takie jak wymienione w pętli.
private void odczytajTowary(List<List<string>> wyn) {
if (wyn != null) {
this.OCTM_listaTowarow.Clear();
for (int i = 0; i < wyn.Count; i++) {
// Lista widziana w programie;
this.OCTM_listaTowarow.Add(new TowarModel {
lp = (i + 1).ToString(),
nazwa = wyn[i][1],
czyNieJestSkladowa = this.czyTowarNieNalezyDoProduktu(this.db.TowaryISkladniki_selectProduktyTowaru(wyn[i][1]))
});
}
}
else Wiadomosci.utrataPolaczeniaSQL();
}
Wyszukiwanie realizuję tak:
this.DTM_dodawanyTowar to właśnie fraza wyszukiwania i przy okazji towar, który można dodać do kolekcji jeżeli w niej nie występuje, ale to mniej ważne.
private void _znajdzTowar() {
string towar = this.DTM_dodawanyTowar.ToLower();
string temp = null;
if (towar != "") {
for (int i = 0; i < this.OCTM_listaTowarow.Count; i++) {
this.OCTM_listaTowarow[i].widocznosc = "Visible";
temp = this.OCTM_listaTowarow[i].nazwa.ToLower();
if (!temp.Contains(towar))
this.OCTM_listaTowarow[i].widocznosc = "Collapsed";
}
}
else { // Po skasowaniu frazy wyszukiwania do zera program pokazuje wszystkie rekordy
for (int i = 0; i < this.OCTM_listaTowarow.Count; i++)
this.OCTM_listaTowarow[i].widocznosc = "Visible";
}
}
Bardzo proszę o pomoc, bo o ile przy małej ilości danych ustawienie ScrollViewer.CanContentScroll na False daje radę o tyle przy większej ilości rekordów ładowanie całości danych trwa wieki.
Pozdrawiam
Grzesiek.