ItemsControl

时间:2016-04-20 12:21:41

标签: c# wpf xaml mvvm

我想创建一个绑定到对象列表的水平布局,并显示一些信息。我希望此控件中控件的大小可以填充控件,就像UniformGrid一样。 问题是,我不希望控件的宽度均匀分布,而是基于对象本身的属性进行加权。

我认为使用自定义ItemsPanelTemplate的ItemsControl是一个很好的策略,因为它可以与UniformGrid一起使用:

<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>

绑定到视图模型:

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; }
}

一个想法是切换到普通网格并使用ColumnDefinitions * -width行为(如(25*,50*,25*)但绑定为Weight*),但我无法弄清楚如何做到这一点。 / p>

2 个答案:

答案 0 :(得分:2)

使用自定义Panel实现这会更容易。我会选择这样的东西:

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;
    }
}

用法

    <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>

答案 1 :(得分:-1)

UniformGrid提供了一种在网格中排列内容的方法,其中网格中的所有单元格具有相同的大小。 我用WrapPanel尝试了你的例子,我认为结果就是你需要的。 所以只需将UniformGrid更改为WrapPanel或StackPanel(Orientation =&#34; Horizo​​ntal&#34;)。 请参见截图 WrapPanel