2017-10-04 1 views
0

Ich versuche derzeit, ein Steuerelement zu erstellen, das ähnlich wie eine VariableGridView, aber statt Höhen und Breiten vorberechnet mit Spalten/Zeilen überspannen, würde der Inhalt die Elemente Höhe steuern . Mit einer Spaltenspanne, die die Steuerbreite bestimmt. Sie können ein WIP-Beispiel finden.UWP Custom Panel Größe basierend auf dem Panel Children's Höhe angeordnet

Das einzige Problem, das ich derzeit habe, ist die anfängliche Belastung des Steuerelements. Wenn sich das Steuerelement in einem ScrollViewer befindet und seine Höhe die Höhe des Fensters/Parents überschreitet, wird nicht gescrollt. Siehe unten:

Scrollbar fills the right hand side

Doch sobald ich die Größe des Fensters, das Scrollen richtig funktioniert wie erwartet. Siehe unten:

You can see here the scrollbar has fixed itself and is the right size for the content of the Panel

es schwierig sein könnte, um zu sehen, aber wenn man sich den dunkleren Teil der Scrollbar auf der rechten Seite können Sie sehen, es selbst nicht richtig auf dem Anfangslast bemessen.

Ich vermute, ich mache einen Fehler bei den Kontrollen MeasureOverride Verfahren jedoch kann ich nicht sehen, was ich falsch mache:

protected override Size MeasureOverride(Size availableSize) { 
    // Need to use this method LimitUnboundedSize as when within a 
    // ScrollViewer an infinite height is supplied within the availableSize 
    var desiredSize = LimitUnboundedSize(availableSize); 
    UpdateColumnOffsets(); 
    foreach (var child in Children) { 
    child.Measure(desiredSize); 
    } 
    return desiredSize; 
} 

private Size LimitUnboundedSize(Size input) { 
    if (Double.IsInfinity(input.Height)) { 
    var scrollViewer = this.FindAscendant<ScrollViewer>(); 
    var contentHeight = scrollViewer.ViewportHeight.Equals(0) 
     ? Window.Current.Bounds.Height : scrollViewer.ViewportHeight; 
    input.Height = (contentHeight >= GetMaxOffset ? contentHeight : 
     GetMaxOffset); 
    } 
    return input; 
} 

Wie kann ich die Höhe meiner Einzelteile gehen berechnen nehmen bevor ich die Größe meines Controls festlege?

+0

ich die Differenz nach Ihrer App herunterladen sehen können. Das Problem liegt daran, dass Sie beim Initialisieren etwas gesetzt haben und das GetMaxOffset immer höher ist als die Inhaltshöhe, nachdem Sie die Benutzeroberfläche geändert haben. Bei der Initialisierung wird GetMaxOffset auf 10 gesetzt, danach wird es jedoch nicht mehr auf das Original zurückgesetzt. Warum lässt man nicht einfach die Höhe als Infinity? –

+0

Leider kann ich nicht zulassen, dass die Höhe unendlich ist, sie wird abstürzen, wenn sie unendlich ist. Zitat aus [hier] (https://docs.microsoft.com/en-us/windows/uwp/layout/boxpanel-example-custom-panel) - "Das Panel selbst kann jedoch keine Größe mit einer unendlichen Zahl zurückgeben Wert von MeasureOverride, der während des Layouts eine Ausnahme auslöst. " – jsmyth886

Antwort

0

Ich konnte mein eigenes Problem lösen. Ich musste die Platzierung meiner Karten vor dem Arrangement herausfinden. Auf diese Weise werden die columnOffsets berechnet und ich kann die Höhe des Panels vom maximalen Spaltenoffset abgrenzen.

Ich habe nicht den GitHub Repo noch aktualisiert, aber hier ist der Code, der für diese Arbeit aktualisiert werden muss:

protected override Size ArrangeOverride(Size finalSize) { 
    foreach (var child in Children) { 
    var resizable = child as IArrangeable; 
    resizable?.Arrange(pointDictionary.GetValueOrDefault(resizable.Card)); 
    } 
    return finalSize; 
} 

private double GetMaxOffset { 
    get { return columnOffsetY.Max(); } 
} 

protected override Size MeasureOverride(Size availableSize) { 
    var desiredSize = availableSize; 
    UpdateColumnOffsets(); 
    foreach (var child in Children) { 
    child.Measure(desiredSize); 
    CreateOffsetCache(child); 
    } 

    if (Double.IsPositiveInfinity(desiredSize.Height)) 
    desiredSize.Height = GetMaxOffset; 

    return desiredSize; 

} 

private Dictionary<Card, Point> pointDictionary; 

private void CreateOffsetCache(UIElement child) { 
    var arrangeable = child as IArrangeable; 
    if (arrangeable == null) return; 
    var card = arrangeable.Card; 
    var useColumnOffset = columnOffsetY[card.Column] < columnOffsetY[card.Column + card.ColumnSpan - 1] 
    ? columnOffsetY[card.Column + card.ColumnSpan - 1] : columnOffsetY[card.Column]; 
    var point = new Point(columnOffsetX[card.Column], useColumnOffset); 
    pointDictionary[card] = point; 
    SetColumnOffsetY(card.Column, card.ColumnSpan, child.DesiredSize.Height); 
}