2016-04-20 9 views
3

Ich möchte ein horizontales Layout erstellen, das an eine Liste von Objekten mit einigen anzuzeigenden Informationen gebunden ist. Ich möchte die Größe der Steuerelemente in diesem Steuerelement, um das Steuerelement zu füllen, wie das UniformGrid tut. Die Sache ist, ich möchte nicht die Breiten der Kontrolle gleichmäßig verteilt werden, sondern eher gewichtet, basierend auf einer Eigenschaft im Objekt selbst.Gewichtete Verteilung von untergeordneten Elementen in ItemsControl

dachte ich ein Item mit einem benutzerdefinierten Itemspaneltemplate eine gute Strategie sein würde, weil es mit einem Uniform gut funktioniert:

<ItemsControl x:Name="itemsControl" ItemsSource="{Binding MyResults}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <UniformGrid Rows="1" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Border BorderBrush="Black" BorderThickness="1"> 
       <TextBlock Width="{Binding Weight}" Text="{Binding Weight}" /> 
      </Border> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Bound der Ansicht Modell:

public class MainViewModel : PropertyChangedBase 
{ 
    public List<MyTestClass> MyResults { get; set; } = new List<MyTestClass>() 
    { 
     new MyTestClass() { Weight = 25 }, 
     new MyTestClass() { Weight = 50 }, 
     new MyTestClass() { Weight = 25 } 
    }; 
} 

public class MyTestClass 
{ 
    public int Weight { get; set; } 
} 

Eine Idee ist Wechseln Sie in ein gewöhnliches Grid und verwenden Sie das ColumnDefinitions * -Breite-Verhalten (wie (25*,50*,25*) aber gebunden als Weight*), aber ich kann nicht herausfinden, wie das geht.

Antwort

2

Dies wäre viel einfacher mit benutzerdefinierten Panel Implementierung zu tun. Ich würde mit so etwas wie dies gehen:

public class WeightedPanel : Panel 
{ 
    public static double GetWeight(DependencyObject obj) 
    { 
     return (double)obj.GetValue(WeightProperty); 
    } 

    public static void SetWeight(DependencyObject obj, double value) 
    { 
     obj.SetValue(WeightProperty, value); 
    } 

    public static readonly DependencyProperty WeightProperty = 
     DependencyProperty.RegisterAttached("Weight", typeof(double), typeof(WeightedPanel), new PropertyMetadata(1.0)); 

    private double totalWeight_; 
    protected override Size MeasureOverride(Size availableSize) 
    { 
     totalWeight_ = 0; 
     foreach (UIElement child in InternalChildren) 
     { 
      totalWeight_ += WeightedPanel.GetWeight(child); 
      child.Measure(availableSize); 
     } 

     return new Size(0, 0); 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     double offset = 0; 
     foreach (UIElement child in InternalChildren) 
     { 
      var weight = WeightedPanel.GetWeight(child); 
      var width = finalSize.Width * weight/totalWeight_; 

      child.Arrange(new Rect(new Point(offset, 0), new Size(width, finalSize.Height))); 

      offset += width; 
     } 

     return finalSize; 
    } 
} 

Nutzungs

<local:WeightedPanel> 
     <Border local:WeightedPanel.Weight="25" Background="Green"></Border> 
     <Border local:WeightedPanel.Weight="50" Background="Red"></Border> 
     <Border local:WeightedPanel.Weight="25" Background="Blue"></Border> 
    </local:WeightedPanel> 
+0

Das sieht wie eine wirklich nette Lösung aus. Aber ich brauche horizontalen Fluss. Ich werde versuchen, dies anzupassen, um eine horizontale Ausrichtung zu verwenden. – FishySwede

+0

Ich änderte die ArrangeOverride zu tun: {var width = finalSize.Width * Gewicht/totalWeight_; child.Arrange (neues Rect (neuer Punkt (Offset, 0), neue Größe (width, finalSize.Height))); Offset + = Breite;}. Wenn Sie Ihre Antwort mit diesem aktualisieren, werde ich mehr als glücklich, es als die Antwort auf meine Frage zu akzeptieren – FishySwede

-1

Uniform eine Möglichkeit bietet, Inhalte in einem Raster anzuordnen, wo alle Zellen im Raster die gleiche Größe haben. Ich habe Ihr Beispiel mit WrapPanel versucht und ich denke, das Ergebnis ist, was Sie brauchen. Ändern Sie also UniformGrid in WrapPanel oder StackPanel (mit Orientation = "Horizontal"). Siehe im Screenshot WrapPanel

+0

Das ist ziemlich nah an dem, was ich will, aber ich möchte die Elemente füllen den übergeordneten Container mit dem Fenster auf der Größe skalieren usw. Das StackPanel und WrapPanel erlaubt nur feste Breiten – FishySwede

Verwandte Themen