2017-09-18 4 views
0

Ich versuche gerade, ein Dictionary anzuzeigen (das in einem Dictionary selbst gespeichert ist).WPF ListView-Elemente, die mit individueller Höhe angezeigt werden sollen

Ich begann zunächst mit einem UniformGrid als ItemsPanelTemplate, aber ziemlich schnell, die anzuzeigenden Elemente können individuelle Höhen haben.

Ich habe so weit, dass ich den gesamten Inhalt mit dem UniformGrid anzeigen kann, aber es scheint nicht zu funktionieren mit einem Grid oder StackPanel als ItemsPanelTemplate.

Der folgende Code funktioniert gut, mit dem Nachteil, dass jeder Operation-Block die gleiche Höhe hat, obwohl ihre Höhe variabel sein kann. Nach einigem Nachdenken kam ich zu dem Schluss, dass ein StackPanel am besten zu verwenden wäre, da die Operationen gezeigt werden würden, die sich gegenseitig die Höhe nehmen, die sie benötigten. Aber als ich es versuchte, relatierte ich sie nehmen nur einen Bruchteil der ListView Höhe.

Erwähnenswert: Die Operation-UserControl berechnet selbst ihre Höhe und baut ihr Layout entsprechend. Es benötigt also nicht den Platz, der benötigt wird, um den gesamten Inhalt anzuzeigen, sondern zeigt den Inhalt an, der in den verfügbaren Platz passt.

Also wie kann ich erreichen, dass die ListViewItems (= Operationen) die volle Höhe der ListView nehmen?

EDIT: Klarstellung
wenn das beschriebene Verhalten nicht möglich ist, mit jeder oben Steuerung erwähnt, aber andere die benötigte funtionality bieten könnte, lassen Sie mich wissen ...

EDIT2: einige Beispiele
Anzahl der verfügbaren Speicherplatz: 500
Keine Bildlaufleiste.
Nebenbei bemerkt: Es gibt keine maxItemLimit ist, aber es ist sehr unwahrscheinlich, dass die ItemCount 10.

Gegeben 1 Punkt überschreiten würde: würde
(benötigten Speicherplatz alle Inhalte 300 anzuzeigen) Dieser einzelne Artikel 300

bei 2 Artikel: (diese müssten 150 und 200 Platz)
Beide Produkte würden dort in voller Größe angezeigt werden: (. Vermutlich nur mit einem Stackpanel in Betrieb) 150, 200.

gegeben 10 Produkte
Diese 10 würden gleichmäßig oder relativ zur voll gewünschten Größe in den 500 ausgedrückt werden (also 50 pro Stück).
Beide Verhaltensweisen wären in Ordnung.

UniformGrid vs StackPanel

<UserControl x:Name="vDay" x:Class="RefServiceClient.Day" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="clr-namespace:RefServiceClient" 
     mc:Ignorable="d" 
     d:DesignHeight="60" d:DesignWidth="120" 
     MinHeight="40"> 

<Grid x:Name="gridDay" 
     Width="{Binding ActualWidth, ElementName=vDay, Mode=OneWay}" 
     Height="{Binding ActualHeight, ElementName=vDay, Mode=OneWay}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 

    <Grid x:Name="DayHeader" Grid.Row="0"> 
     <!--containing header info: several textboxes, which are irrelevant for the question--> 

     <TextBox x:Name="dayShortname" 
       Grid.Row="0" Grid.Column="1" 
       VerticalAlignment="Center" 
       HorizontalAlignment="Stretch" 
       Margin="1" 
       Text="{Binding Path=Value.DayShortname}"/> 
    </Grid> 

    <ListView x:Name="operations" Grid.Row="1" Background="Aqua" 
       ItemsSource="{Binding Path=Value.OperationList}" 
       HorizontalAlignment="Stretch" 
       VerticalAlignment="Stretch" 
       HorizontalContentAlignment="Stretch" 
       VerticalContentAlignment="Stretch" 
       ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
       ScrollViewer.VerticalScrollBarVisibility="Disabled"> 

     <ListView.ItemTemplate> 
      <DataTemplate> 
       <local:Operation Background="Crimson" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch"/> 
       <!--<local:Operation Background="Crimson" />--> 
      </DataTemplate> 
     </ListView.ItemTemplate> 

     <ListView.ItemsPanel> 
      <ItemsPanelTemplate> 

       <!--<Grid Grid.IsSharedSizeScope="True"/>--> 
       <!--<StackPanel/>--> 
       <!--<VirtualizingStackPanel Orientation="Vertical"/>--> 
       <UniformGrid Columns="1"/> 
      </ItemsPanelTemplate> 
     </ListView.ItemsPanel> 
    </ListView> 

</Grid> 

+0

Ich denke, das Problem ist Ihre 'local: Operation' Implementierung. Wenn es eine angemessene Höhe erfordern würde, würde die "ListView" mit "StackPanel" als Gegenstandsfläche angemessenen Platz für jedes Listenelement geben. – grek40

+0

@ grek40 Ich kann dir da folgen. Da die ListView jedoch mehrere 'local: Operation' enthalten kann und der verfügbare Speicherplatz gleich bleibt, gibt es meines Erachtens nur eine Lösung: Die' local: Operations' zeigen ein Minimum an Inhalt (Header-Daten) und Zeige Detail-Daten wenn mehr Platz zur Verfügung steht. Andernfalls (wenn die Operation immer den benötigten Platz einnimmt), wäre ich nicht in der Lage, alle "Operationen" ohne eine Bildlaufleiste anzuzeigen. – Evaniar

+1

Haben Sie versucht, eine 'DataTemplate' mit einem' StackPanel' anstelle des 'UserControl' zu verwenden? – XAMlMAX

Antwort

0

Sie könnten eine eigene Platte erstellen, die nach Ihren Regeln Ihre Artikel arrangiert. Dann müssen Sie Ihre Artikel nur so gestalten, dass sie für jede Größe, die sie aufnehmen dürfen, gut angezeigt werden.

Eine grobe Skizze der Platte könnte wie folgt aussehen:

public class SqueezeStackPanel : Panel 
{ 
    protected override Size MeasureOverride(Size availableSize) 
    { 
     var desiredHeight = 0.0; 
     foreach (UIElement child in InternalChildren) 
     { 
      child.Measure(availableSize); 
      desiredHeight += child.DesiredSize.Height; 
     } 

     if (availableSize.Height < desiredHeight) 
     { 
      // we will never go out of bounds 
      return availableSize; 
     } 
     return new Size(availableSize.Width, desiredHeight); 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     // measure desired heights of children in case of unconstrained height 
     var size = MeasureOverride(new Size(finalSize.Width, double.PositiveInfinity)); 

     var startHeight = 0.0; 
     var squeezeFactor = 1.0; 
     // adjust the desired item height to the available height 
     if (finalSize.Height < size.Height) 
     { 
      squeezeFactor = finalSize.Height/size.Height; 
     } 

     foreach (UIElement child in InternalChildren) 
     { 
      var allowedHeight = child.DesiredSize.Height * squeezeFactor; 
      var area = new Rect(new Point(0, startHeight), new Size(finalSize.Width, allowedHeight)); 
      child.Arrange(area); 
      startHeight += allowedHeight; 
     } 

     return new Size(finalSize.Width, startHeight); 
    } 
} 

Dieses Panel kann in den ItemsPanelTemplate Ihre ListView mit behinderten Bildlaufleisten verwendet werden.

+0

bis jetzt. Ich werde das versuchen (vielleicht in Verbindung mit Сергей Боголюбов Vorschlag) und melden Sie zurück ... – Evaniar

+0

Nochmals vielen Dank für das Zeigen mir in die richtige Richtung – Evaniar

0

Kommt drauf an. Ich gebe dir eine Option. Zuerst. Implementieren Sie beispielsweise Boolean AttachedProperty und geben Sie an, ob diese bestimmte Instanz eine bestimmte Größe haben soll. Wenn 0/1 nicht ausreicht, deklarieren Sie eine entsprechende Aufzählung. Zweite. Erweitern Sie das vorhandene StackPanel, überschreiben Sie die entsprechenden geschützten Elemente. Zumindest MeasureOverride/ArrangeOverride. Dort können Sie den Wert der entsprechenden angehängten Eigenschaft ablesen und entscheiden, wie groß oder klein es sein soll. Klingt es wie eine Lösung? Falls ja, kann ich einige Beispiele nennen.

+0

auf welches Objekt beziehen Sie sich in Schritt1? ListView oder ChildElement (= Operation)? Abgesehen davon schlagen Sie eine ähnliche Lösung wie grek40 vor. nur dass Sie StackPanel statt Panel erweitern würden. Was ist der Vorteil der Erweiterung von StackPanel anstelle von Panel? – Evaniar

Verwandte Themen