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