2017-09-28 119 views
2

WrapPanelsを持つ複数のItemsControlを含むWPF ListViewがあります。 スクロールバーが表示されていない限り、アイテムは期待どおりに折り返されます。表示されているスクロールバーがある場合、ウィンドウの幅が狭くなると、左の列に移動する必要がある項目の垂直スペースを要求するWrapPanelが表示されますが、項目は移動しません。スクロールバーを使用してスクロールすると、項目は正しい列にジャンプします。WPF ListBoxItem with WrapPanelは、垂直スクロールバーが表示されているときにラップしません。

誰かがこれに遭遇し、誰かが解決策を知っていますか?

ムービークリップの方がはっきりしますが、下の写真では、ステップとその結果を説明しようとしています。プロジェクトのコードは写真の下に掲載されています。

ませんスクロールバー、ラッピングが正常に動作します: No scrollbar, wrapping works fine

ませんスクロールバー、でも狭い窓、ラッピングはまだ正常に動作します: No scrollbar, even narrower window, wrapping still works fine

スクロールバーが表示され、ラッピングはまだ大丈夫です。 A scrollbar is visible, wrapping is still ok

スクロールバーが表示され、画面が狭く、緑色wrappanel垂直空間が左端の列に移動しなければならない項目に記載されているが、アイテムが移動しないことを示している: 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

をスクロールバーを使用した後、

<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
After using the scrollbar, the items jump to the correct column

:項目が正しい列にジャンプ

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

ListBoxのSizeChangedイベントを購読し、UpdareLayout()を呼び出して何か違いがありますか?または、より正確にWrapPanelに名前を付け、レイアウトを更新します。 – shadow32

+0

@ shadow32私は、視覚的なツリーのほぼすべてについて、UpdateLayout()、InvalidateArrange()、InvalidateMeasure()、InvalidateParentsOfModifiedChildren()、InvalidateProperty(ActualHeightProperty)、InvalidateProperty(ActualWidthProperty)を試しました。 – eriksmith200

答えて

1

これは、ListViewのスクロールで非常に良いではないことが判明します。外側のListViewのスクロールバーを無効にしてScrollViewerでラップすると、内部のWrapPanelsと含まれているアイテムが期待どおりに動作します。これを理解するために私に1日かかりました。

関連する問題