WPF ListBoxItem与WrapPanel不匹配';垂直滚动条可见时不换行

WPF ListBoxItem与WrapPanel不匹配';垂直滚动条可见时不换行,wpf,listview,itemscontrol,wrappanel,Wpf,Listview,Itemscontrol,Wrappanel,我有一个WPF列表视图,其中包含多个具有Wrappanel的ItemsControl。 只要没有可见的滚动条,项目就会按预期进行包装。当有一个滚动条可见时,当窗口变得不那么宽时,我可以看到WrapPanel为需要移动到左侧列的项目提供了垂直空间,但项目不移动。使用滚动条滚动后,项目会跳转到正确的列 有人遇到过这种情况吗?有人知道解决方法吗 电影剪辑会更清晰,但在下面的图片中,我试图解释步骤和发生了什么。项目代码张贴在图片下方 无滚动条,包装工作正常: 没有滚动条,即使窗口更窄,包装仍然可以正常

我有一个WPF列表视图,其中包含多个具有Wrappanel的ItemsControl。 只要没有可见的滚动条,项目就会按预期进行包装。当有一个滚动条可见时,当窗口变得不那么宽时,我可以看到WrapPanel为需要移动到左侧列的项目提供了垂直空间,但项目不移动。使用滚动条滚动后,项目会跳转到正确的列

有人遇到过这种情况吗?有人知道解决方法吗

电影剪辑会更清晰,但在下面的图片中,我试图解释步骤和发生了什么。项目代码张贴在图片下方

无滚动条,包装工作正常:

没有滚动条,即使窗口更窄,包装仍然可以正常工作:

滚动条可见,包装仍然正常:

一个滚动条可见,屏幕更窄,绿色的包装显示应该移动到最左边列的项目占用垂直空间,但项目不移动:

使用滚动条后,项目跳转到正确的列:

main window.xaml

<Window x:Class="Wrapping.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="800" Width="600">
<Window.Resources>

    <DataTemplate x:Key="DetailReadOnlyTemplate">
        <Grid Width="75" Height="15" Margin="2" Background="Green"/>
    </DataTemplate>

    <DataTemplate x:Key="MainObjectReadOnlyTemplate">
        <StackPanel>
            <Grid VerticalAlignment="Top">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Number}"/>
                <TextBlock Text="Some text" Grid.Column="1" HorizontalAlignment="Right"/>
            </Grid>

            <ItemsControl ItemsSource="{Binding DetailObjects}" 
                          ItemTemplate="{StaticResource DetailReadOnlyTemplate}"
                          Background="LightGreen">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </StackPanel>
    </DataTemplate>

</Window.Resources>

<ListView ItemsSource="{Binding MainObjects}"
          SelectedItem="{Binding SelectedMainObject}"
          ScrollViewer.HorizontalScrollBarVisibility="Disabled"
          ItemTemplate="{StaticResource MainObjectReadOnlyTemplate}"
          HorizontalContentAlignment="Stretch"
          Background="Bisque"/>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : INotifyPropertyChanged
{
    private static readonly Random Random = new Random();

    public MainWindow()
    {
        DataContext = this;

        InitializeComponent();

        MainObjects = new ObservableCollection<MainObject>();

        for (var i = 0; i < 10; i++)
        {
            MainObjects.Add(CreateMainObject(i));
        }
    }

    private ObservableCollection<MainObject> _mainObjects;
    public ObservableCollection<MainObject> MainObjects
    {
        get => _mainObjects;
        set
        {
            _mainObjects = value;
            OnPropertyChanged();
        }
    }

    private MainObject _selectedMainObject;
    public MainObject SelectedMainObject
    {
        get => _selectedMainObject;
        set
        {
            _selectedMainObject = value;
            OnPropertyChanged();
        }
    }

    private MainObject CreateMainObject(int n)
    {
        return new MainObject
        {
            DisplayText = "Main object " + n,
            Number = n,
            DetailObjects = GenerateDetailObjects()
        };
    }

    private ObservableCollection<DetailObject> GenerateDetailObjects()
    {
        var detailObjects = new ObservableCollection<DetailObject>();

        for (var i = 0; i < Random.Next(2, 4); i++)
        {
            detailObjects.Add(new DetailObject
            {
                DisplayText = "Detail " + i,
                Value = GenerateRandomString(Random.Next(3, 8))
            });
        }

        return detailObjects;
    }

    public static string GenerateRandomString(int length)
    {
        const string chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        return new string(Enumerable.Repeat(chars, length).Select(s => s[Random.Next(s.Length)]).ToArray());
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
公共部分类主窗口:INotifyPropertyChanged
{
私有静态只读随机=新随机();
公共主窗口()
{
DataContext=this;
初始化组件();
MainObjects=新的ObservableCollection();
对于(变量i=0;i<10;i++)
{
添加(CreateMainObject(i));
}
}
私有可观测集合_mainObjects;
公共可观察收集主要对象
{
get=>\u main对象;
设置
{
_主要对象=价值;
OnPropertyChanged();
}
}
private main object\u selectedmain object;
公共主对象SelectedMainObject
{
get=>\u selectedMainObject;
设置
{
_selectedMainObject=值;
OnPropertyChanged();
}
}
私有MainObject CreateMainObject(int n)
{
返回新的主对象
{
DisplayText=“Main object”+n,
数字=n,
DetailObjects=GenerateDetailObjects()
};
}
私有ObservableCollection GeneratedDetailObjects()
{
var detailObjects=新的ObservableCollection();
对于(var i=0;is[Random.Next(s.length)]).ToArray();
}
公共事件属性更改事件处理程序属性更改;
[NotifyPropertyChangedInvocator]
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
虚拟对象:

public class MainObject : INotifyPropertyChanged
{
    private int _number;
    public int Number
    {
        get => _number;
        set
        {
            _number = value;
            OnPropertyChanged();
        }
    }

    private string _displayText;
    public string DisplayText
    {
        get => _displayText;
        set
        {
            _displayText = value;
            OnPropertyChanged();
        }
    }

    private ObservableCollection<DetailObject> _detailObjects;
    public ObservableCollection<DetailObject> DetailObjects
    {
        get => _detailObjects;
        set
        {
            _detailObjects = value;
            OnPropertyChanged();
        }
    } 

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class DetailObject : INotifyPropertyChanged
{
    private string _displayText;
    public string DisplayText
    {
        get => _displayText;
        set
        {
            _displayText = value;
            OnPropertyChanged();
        }
    }

    private string _value;
    public string Value
    {
        get => _value;
        set
        {
            _value = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
public类主对象:INotifyPropertyChanged
{
私人整数;
公共整数
{
get=>\u编号;
设置
{
_数字=数值;
OnPropertyChanged();
}
}
私有字符串_displayText;
公共字符串显示文本
{
获取=>\u显示文本;
设置
{
_显示文本=值;
OnPropertyChanged();
}
}
私有ObservableCollection\u detailObjects;
公共ObservableCollection详细信息对象
{
get=>\u detailObjects;
设置
{
_detailObjects=值;
OnPropertyChanged();
}
} 
公共事件属性更改事件处理程序属性更改;
[NotifyPropertyChangedInvocator]
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共类DetailObject:INotifyPropertyChanged
{
私有字符串_displayText;
公共字符串显示文本
{
获取=>\u显示文本;
设置
{
_显示文本=值;
OnPropertyChanged();
}
}
私有字符串_值;
公共字符串值
{
获取=>\u值;
设置
{
_价值=价值;
OnPropertyChanged();
}
}
公共事件属性更改事件处理程序属性更改;
[NotifyPropertyChangedInvocator]
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}

原来ListView不太擅长滚动。禁用外部ListView上的滚动条并将其包装到ScrollViewer中后,内部包装窗格和包含的项的行为与预期一致。我花了一天时间才弄明白这一点。

订阅ListBox的SizeChanged事件并在其上调用DareLayout()会有什么不同吗?或者更准确地命名包装并更新其布局。@shadow32我尝试了UpdateLayout()、InvalidateArrange()、InvalidateMeasure()、InvalidateParentsOfModifiedChildren()、InvalidateProperty(Ac