WrapPanelsを持つ複数のItemsControlを含むWPF ListViewがあります。 スクロールバーが表示されていない限り、アイテムは期待どおりに折り返されます。表示されているスクロールバーがある場合、ウィンドウの幅が狭くなると、左の列に移動する必要がある項目の垂直スペースを要求するWrapPanelが表示されますが、項目は移動しません。スクロールバーを使用してスクロールすると、項目は正しい列にジャンプします。WPF ListBoxItem with WrapPanelは、垂直スクロールバーが表示されているときにラップしません。
誰かがこれに遭遇し、誰かが解決策を知っていますか?
ムービークリップの方がはっきりしますが、下の写真では、ステップとその結果を説明しようとしています。プロジェクトのコードは写真の下に掲載されています。
ませんスクロールバー、ラッピングが正常に動作します:
ませんスクロールバー、でも狭い窓、ラッピングはまだ正常に動作します:
スクロールバーが表示され、ラッピングはまだ大丈夫です。
スクロールバーが表示され、画面が狭く、緑色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
:項目が正しい列にジャンプ
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 = "abcdefghijklmnopqrstuvwxyz";
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));
}
}
ListBoxのSizeChangedイベントを購読し、UpdareLayout()を呼び出して何か違いがありますか?または、より正確にWrapPanelに名前を付け、レイアウトを更新します。 – shadow32
@ shadow32私は、視覚的なツリーのほぼすべてについて、UpdateLayout()、InvalidateArrange()、InvalidateMeasure()、InvalidateParentsOfModifiedChildren()、InvalidateProperty(ActualHeightProperty)、InvalidateProperty(ActualWidthProperty)を試しました。 – eriksmith200