Skip to content

Listbox Image Binding Is Slow and Freezes UI #9984

@xDreamms

Description

@xDreamms

Description

 public static async Task<BitmapImage> GetImage(string url,ImageType imageType)
 {
     var bitmapImage = new BitmapImage(new Uri(url,UriKind.Absolute));
     return bitmapImage;
}
<ListBox  ScrollViewer.CanContentScroll="True" MaxHeight="500" 
  VirtualizingPanel.IsVirtualizing="true" 
  VirtualizingPanel.VirtualizationMode="Recycling" ItemsSource="{Binding PopularMovies, Mode=OneWay, IsAsync=True}"  Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" SelectionChanged="MoviesDisplay_OnSelectionChanged" ScrollViewer.ScrollChanged="MoviesDisplay_OnScrollChanged"  ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="Transparent" x:Name="MoviesDisplay">

    <b:Interaction.Behaviors>
        <local:IgnoreMouseWheelBehavior />
    </b:Interaction.Behaviors>
    <ItemsControl.Resources>
        <Style x:Key="ScaleStyle" TargetType="Image">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Grid.ZIndex" Value="1"/>
                    <Setter Property="RenderTransform">
                        <Setter.Value>
                            <ScaleTransform ScaleX="1.1" ScaleY="1.1"/>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ItemsControl.Resources>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsSelected" Value="{Binding Content.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource Self}}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <ContentPresenter/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Cursor="Hand" Margin="0 0 20 0" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"></RowDefinition>
                    <RowDefinition Height="0.052*"></RowDefinition>
                    <RowDefinition Height="0.05*"></RowDefinition>
                </Grid.RowDefinitions>

                <Viewbox HorizontalAlignment="Left" Grid.Row="0" Grid.Column="0">
                    <Image RenderTransformOrigin="0.5,0.5" Style="{StaticResource ScaleStyle}"  Source="{Binding Bitmap, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"></Image>
                </Viewbox>

                <Viewbox MaxWidth="200" HorizontalAlignment="Left" Grid.Row="1">
                    <TextBlock   TextWrapping="Wrap" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Foreground="White"></TextBlock>
                </Viewbox>

                <Grid Grid.Row="2" Grid.Column="0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="0.3*"></ColumnDefinition>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>

                    <Viewbox HorizontalAlignment="Left">
                        <materialDesign:RatingBar
x:Name="ReadOnlyRatingBar"
IsReadOnly="True"
Value="{Binding Rating, UpdateSourceTrigger=PropertyChanged}"></materialDesign:RatingBar>
                    </Viewbox>

                    <Viewbox Margin="10 0 0 0" Grid.Column="1" HorizontalAlignment="Left">
                        <TextBlock Text="{Binding RatingNumber, UpdateSourceTrigger=PropertyChanged}" Foreground="#767676"></TextBlock>
                    </Viewbox>
                </Grid>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel VirtualizingStackPanel.IsVirtualizing="True"  VirtualizingStackPanel.VirtualizationMode="Recycling" IsItemsHost="True" Orientation="Horizontal"  />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>
public static async Task GetPopularMoviesAsync(string language, int page)
{
    PopularMovies.Clear();
    var popularMovies = await client.GetMoviePopularListAsync(language, page);
    foreach (var movie in popularMovies.Results)
    {
        Movie mov = new Movie()
        {
            Bitmap = await GetImage(client.GetImageUrl("w500", movie.PosterPath).AbsoluteUri,ImageType.Poster),
            Id = movie.Id,
            Name = movie.Title,
            Rating = movie.VoteAverage,
            RatingNumber = movie.VoteAverage.ToString(),
            ShowType = ShowType.Movie,
        };
        if (PopularMovies.Any(x => x.Id == movie.Id))
        {

        }
        else
        {
            PopularMovies.Add(mov);
        }
    }
}

It is slow and freezes UI. Btw I am using https://github.com/jellyfin/TMDbLib. And I read and applied this article: But still slow
https://github.com/RickStrahl/BlogPosts/blob/master/2024-01/Working%20around%20the%20WPF%20Image%20Control%20Blues/WorkingAroundWPFImageControlBlues.md
Btw my 2018 project .net 4.7.2 with same codes runs very fast. What did you change in ImageControl?

Expected behavior

It should work without freezes and fast

Actual behavior

Slow and Freezes UI

Metadata

Metadata

Assignees

No one assigned

    Labels

    InvestigateRequires further investigation by the WPF team.PerformancePerformance related issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions