#c# #.net #wpf #listbox
Вопрос:
коллеги-программисты!
Я только начал изучать WPF, и в рамках своих первых проектов я пытаюсь создать 2 изогнутых списка каруселей рядом с центральным кругом с обеих сторон. Используя пользовательскую панель в списке, мне удалось получить этот результат:
<Grid Margin="7" Height="450">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="300"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="1" Margin="20 0 20 0" PreviewMouseDown="Viewbox_PreviewMouseDown" Style="{StaticResource MainOption}">
<Grid Width="230" Height="230" >
<Ellipse Width="230" Height="230" Stroke="{StaticResource PrimaryDarkColor}" StrokeThickness="2" Fill="Transparent" />
<!--<Ellipse Width="200" Height="200">
<Ellipse.Fill>
<ImageBrush ImageSource="/Assets/Profile.ico" />
</Ellipse.Fill>
</Ellipse>-->
<md:PackIcon Kind="Map" Foreground="White" Width="180" Height="180" Margin="25 10 0 0" />
<TextBlock Text="Map" HorizontalAlignment="Center" VerticalAlignment="Bottom" Foreground="White" Margin="0 0 0 30" Style="{StaticResource MenuItem}"/>
</Grid>
</Viewbox>
<ListView Grid.Column="0" ItemsSource="{Binding LeftMenuItems}" Height="360" FlowDirection="RightToLeft" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<cc:CurvedPanel RadiusX="70"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<!--<Button Content="{Binding Text}" Width="100" Command="{Binding OpenCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" CommandParameter="{Binding Window}"/>-->
<TextBlock Text="{Binding Text}" Style="{StaticResource MenuItem}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Grid.Column="2" ItemsSource="{Binding RightMenuItems}" Height="360" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<cc:CurvedPanel RadiusX="90" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<!--<Button Content="{Binding Text}" Width="100" Command="{Binding OpenCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" CommandParameter="{Binding Window}"/>-->
<TextBlock Text="{Binding Text}" Style="{StaticResource MenuItem}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
public class CurvedPanel : StackPanel
{
public double RadiusX { get; set; }
protected override Size MeasureOverride(Size availableSize)
{
return base.MeasureOverride(availableSize);
}
protected override Size ArrangeOverride(Size finalSize)
{
double angle = 80, centerX = 0, centerY = finalSize.Height / 2, decrement = 20, radiusY = centerY * 0.8, radiusX = 70;
Point prevPoint = new Point(0, 0);
if (Children.Count > 0)
{
foreach (UIElement child in Children)
{
var angleInRadians = AngleToRadian(angle);
Point childPosition = new Point(radiusX * Math.Cos(angleInRadians), radiusY * -Math.Sin(angleInRadians) radiusY);
child.Arrange(new Rect(new Point(childPosition.X, childPosition.Y), new Size(finalSize.Width, child.DesiredSize.Height)));
angle -= decrement;
}
}
return finalSize;
}
private double AngleToRadian(double angle)
{
return angle * (Math.PI / 180);
}
}
But this is far from ideal, because (as image shows) items overlap. Probably because it doesn’t account for item’s size itself. I want to prevent this overlapping, but can’t figure out changes that need to be implemented.
Plus I want to make curved scrollbar, which when scrolling will scroll along curved path. But I have no idea how to do this.
I heard there was once PahtListBox, which could accomplish what I need, but I don’t think this is available in core.
Any help will be greatly appreciated!