TreeView/ScrollView rendering bug with bitmaps?

2019-07-30 16:23发布

问题:

There is a WPF (.NET 3.5) TreeView, which contains bitmaps. Nothing special:

<ControlTemplate x:Key="ctrlOutputTree" TargetType="{x:Type vo:OutputTreeView}">
    <TreeView x:Name="OutputTree" ItemContainerStyle="{DynamicResource TreeViewItemStyle}"
              KeyboardNavigation.TabNavigation="Cycle" SnapsToDevicePixels="True"  MouseDown="OutputTree_MouseDown"
              Loaded="OutputTree_Loaded" RenderOptions.BitmapScalingMode="NearestNeighbor">

        <TreeView.Resources>
            <Style TargetType="TreeViewItem">
                <EventSetter Event="RequestBringIntoView" Handler="OutputTree_RequestBringIntoView"/>
                <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
                <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
            </Style>
        </TreeView.Resources>

        <TreeViewItem  ItemsSource="{Binding Converter={StaticResource featureDiffsSourceCreator},Mode=OneWay}"
                       IsExpanded="True" Margin="0,4,0,0" 
                       KeyDown="AttrDiffTreeviewItem_KeyDown">
        </TreeViewItem>
    </TreeView>
</ControlTemplate> 

TreeViewItems:

<ControlTemplate x:Key="ImageTemplate">
    <Image VerticalAlignment="Top" Margin="3,1,0,0" 
           RenderOptions.BitmapScalingMode="NearestNeighbor"
           RenderOptions.EdgeMode="Aliased"
           Stretch="None">
        <Image.Source>
            <!-- <BitmapImage UriSource="c:\\imageBMP_test.bmp" />-->

            <MultiBinding Converter="{StaticResource imageConverter}">
                <Binding Path=....
            </MultiBinding>
        </Image.Source>
    </v:Image>
</ControlTemplate>

The bitmaps are generated as BitmapSource in imageConverter (from native control).

System::Drawing::Bitmap^ b = System::Drawing::Image::FromHbitmap((IntPtr)aBmp);
IntPtr hb = b->GetHbitmap();
System::Windows::Media::Imaging::BitmapSource^ bs = 
    System::Windows::Interop::Imaging::CreateBitmapSourceFromHBitmap(hb, 
                             System::IntPtr::Zero,
                             Int32Rect(0,0,nWidth,nHeight),
                             BitmapSizeOptions::FromEmptyOptions());

It displays all fine, but when we scroll the tree, sometimes bitmaps becomes distorted. Mostly close to the bottom. Sometimes we need to resize the tree to happen, but it happens sooner or later.

ItemX is text, and the table next to it is the bitmap.

After this, when it's wrong, if I scroll the tree with the scrollbar-position-thumb, just 1 pixel up/down, it becomes sharp and good again. But if I scroll with up/down arrows on the scrollbar, bitmaps remain invalid for a few click (then goes away)

If I replace the BitmapSource generation in XAML MultiBinding/imageConverter --> <BitmapImage UriSource="c:\\imageBMP_test.bmp" , then don't experience this issue. (I have to take care the imageBMP_test.bmp to be 24 bits & 96DPI, otherwise also not good)

If I change the BitmapSource generation to read from file (24 or 32bit bmp with 96dpi):

System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap("c:\\imageBMP24_96dpi_small.bmp");
IntPtr hb = b->GetHbitmap();
System::Windows::Media::Imaging::BitmapSource^ bs = 
    System::Windows::Interop::Imaging::CreateBitmapSourceFromHBitmap(hb, 
                             System::IntPtr::Zero,
                             Int32Rect(0,0,nWidth,nHeight),
                             BitmapSizeOptions::FromEmptyOptions());

Then after some scrolling, I got this:

Any help, idea would be appreciated.

What I tried:
Checked, generated 'BitmapSource' is 96 DPI.
Saved into file all generated 'BitmapSource' - all were fine, while they were distorted on the screen.
I am out of ideas, seems it's a WPF bug? Or maybe video driver? (nvidia quadro/laptop/win7 64bit)

SO IN SHORT

TreeView displays bitmap loaded from file specified in XAML: OK (very small glitches here also sometimes, but those are acceptable)
TreeView displays bitmap from BitmapSource generated: FAILS sometimes (during scroll)

回答1:

I found a solution. Have no clue why it works, but seems to solve the problem:

if in the imageConverter (in a native control) I return BitmapImage^ instead of BitmapSource^, it's ok.
Very strange, but I just create BitmapImage from the BitmapSource, return that, and no problems.
WPF is horrible...