当垂直滚动条可见时,带有WrapPanel的WPF ListBoxItem不会换行

时间:2017-09-28 14:07:47

标签: wpf listview itemscontrol wrappanel

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

有没有人遇到这个并且有人知道解决方案吗?

电影剪辑会更清晰,但在下面的图片中,我尝试解释步骤和发生的事情。该项目的代码发布在图片下方。

没有滚动条,包装工作正常 No scrollbar, wrapping works fine

没有滚动条,甚至更窄的窗口,包装仍然可以正常工作: No scrollbar, even narrower window, wrapping still works fine

滚动条可见,包装仍然正常: A scrollbar is visible, wrapping is still ok

滚动条可见,屏幕较窄,绿色包装纸显示要移动到最左侧列的项目声明垂直空间,但项目不移动: A scrollbar is visible, screen is narrower, the green wrappanel shows that vertical space is claimed for the items that should move to the leftmost column, but the items do not move

使用滚动条后,项目会跳转到正确的列: After using the scrollbar, the items jump to the correct column

MainWindow.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));
    }
}

虚拟对象:

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));
    }
}

1 个答案:

答案 0 :(得分:1)

事实证明,ListView不是很擅长滚动。禁用外部ListView上的滚动条并将其包装在ScrollViewer中后,内部WrapPanel和包含的项按预期运行。我花了一天时间来弄明白这一点。