Позиционирование элементов в ItemsControl - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть ItemsControl привязка к таким данным:

<ItemsControl Name="MainPanel" >
    <ItemsControl.ItemTemplate>
        <DataTemplate>
           <TextBlock Text="{Binding Definition}" TextWrapping="Wrap"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

В моей модели данных у меня есть координата y для каждого элемента, чтобы расположить элемент вертикально на экране и каждый элементимеет переменную высоту (из-за TextWrapping).

Мне нужно, чтобы каждый элемент располагался по координате y, если только он не перекрывается с предыдущим элементом, и в этом случае он помещается ниже предыдущего элемента.

Я подумал использовать свойство Margin для этого, но на самом деле все не так просто ...

Есть идеи, как поступить?

1 Ответ

1 голос
/ 04 апреля 2019

Я думаю, что изменение TextBlock.Margin.Top - это простой способ сделать это.

    <ItemsControl ItemsSource="your model collection"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <!-- Need ItemsControl for calculation. -->
                <TextBlock Text="{Binding Text}" TextWrapping="Wrap"
                           Tag="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}}">
                    <TextBlock.Margin>
                        <MultiBinding Converter="{StaticResource calcOffsetY}">
                            <Binding RelativeSource="{RelativeSource Self}"/>
                            <Binding Path="ActualWidth" RelativeSource="{RelativeSource AncestorType=ItemsControl}"/>
                        </MultiBinding>
                    </TextBlock.Margin>
                </TextBlock>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

И конвертер.

public class CalcOffsetY : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var tbk = (TextBlock)values[0];
        var offsetY = tbk.TranslatePoint(tbk.RenderTransformOrigin, (UIElement)tbk.Tag).Y -
            tbk.Margin.Top;
        var y = ((YourModelType)tbk.DataContext).Y;

        tbk.SetCurrentValue(TextBlock.MarginProperty, new Thickness(tbk.Margin.Left, y > offsetY ? y - offsetY : 0,
            tbk.Margin.Right, tbk.Margin.Bottom));
        tbk.UpdateLayout(); // Update layout immediately, so next item will get correct result.

        return Binding.DoNothing; // Already nothing to do.
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
...