Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在wpf中创建无限中心旋转木马控件_C#_Wpf - Fatal编程技术网

C# 在wpf中创建无限中心旋转木马控件

C# 在wpf中创建无限中心旋转木马控件,c#,wpf,C#,Wpf,我试图在WPF中创建一个无休止的、以中心为中心的旋转木马,就像在这个概念图中一样。我目前提出的解决方案是使用一个列表框,将所有图像加载到一个ObservableCollection中,然后修改它以创建运动的错觉 这个解决方案有两个问题。首先,我似乎无法将它居中。列表框向左对齐,无法使其两侧溢出。无论我的窗口大小如何,都应该在中间显示一个控制台,每一侧显示一个控制台,一半显示一个控制台。 第二个问题没有那么重要,但我正在寻找一种合适的方法来实现这一点,以便以后在选择之间进行更流畅的转换 这是我当

我试图在WPF中创建一个无休止的、以中心为中心的旋转木马,就像在这个概念图中一样。我目前提出的解决方案是使用一个列表框,将所有图像加载到一个ObservableCollection中,然后修改它以创建运动的错觉

这个解决方案有两个问题。首先,我似乎无法将它居中。列表框向左对齐,无法使其两侧溢出。无论我的窗口大小如何,都应该在中间显示一个控制台,每一侧显示一个控制台,一半显示一个控制台。 第二个问题没有那么重要,但我正在寻找一种合适的方法来实现这一点,以便以后在选择之间进行更流畅的转换

这是我当前的代码:

XAML:


我不认为我会像你那样做。即在列表框中添加和删除项目。没有给你足够的位置控制,你将无法做它旋转的平滑动画,这种UI,我认为这将是一种预期:)

我可能会用cliptobunds=true来代替画布。然后只计算位置,你没有做一个圆形旋转木马,所以位置很小,没有缩放


假设您的图像都是100 x 100。所以item0将是@-50,0,item1@50,0(技术上可能是75,0或其他什么,因为你希望它们之间有一些间距,但你知道了),等等,因为你在计算位置,并让它们绝对地靠在画布上,cliptobund=true将在任意一端剪辑这两个对象,您将能够设置旋转的动画。

我对这个答案感到困惑。图形化更好,但是如果没有某种预先制作的可滚动/可选择/可加载的集合容器,您将失去很多功能—ItemsSource、SelectedItem、SelectedIndex等。您对如何使用您的方法实现这些功能有何建议?但正是这些功能阻碍了您的工作。一个预构建的滚动条,如列表框或任何期望项目彼此保持在相同位置的东西。它也将是一个愚蠢的工作包装作为一个滚动期望你从0滚动到X和从X滚动到0。不是以循环的方式。你将不得不重新实现滚动,以使酷的动画去无论如何。如果您想在侧面滚动箭头,可以在重复按钮上制作一些箭头。不要认为你需要选择索引。SelectedItem将只是您单击的图像。第2部分。。。使每个图像位于透明网格的顶部,这样您就不必单击实际图像本身,而是单击周围的正方形。也就是说,如果你有一个圆,除非你有透明的网格背景,你必须点击实际的圆,你将无法点击角落。您可以相当容易地将所有内容封装在自定义控件中。我认为围绕所有内置功能进行工作要比实现动画滚动、包装等并将其放入列表框要困难得多。第3部分:哈哈。。最后,我认为让ListBox在左侧显示部分项是不可行的,因为它希望项0从像素0开始。您可以尝试将一个列表框放置在ClipToBounds=True的网格中,并将列表框的边距设置为-50,然后查看这是否符合您的喜好。这将把左边的项目一分为二,但你永远不会在左边有一个完整的项目,滚动条也会被剪掉。就我个人而言,对于这个UI,我无论如何都会做一个覆盖滚动箭头。一个标准的滚动条看起来很奇怪。你的意思和这个例子相似吗?我会尝试一下,但如果我没有使用列表框或类似的。。。然后如何获取当前选定的项目?我将查看PivotControl的源代码,类似于Windows Phone中的无休止滚动控件,以了解它们是如何做到这一点的
<Window x:Class="SystemMenu.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

<DockPanel>
    <Button Content="left" Height="20" Click="Left_Click" DockPanel.Dock="Top" />
    <Button Content="right" Height="20" Click="Right_Click" DockPanel.Dock="Top" />

    <ListBox x:Name="LoopPanel" ItemsSource="{Binding Path=SampleData}" SelectedIndex="3" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.CanContentScroll="False">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                    <Image Source="{Binding}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</DockPanel>
    public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    ObservableCollection<string> sampleData = new ObservableCollection<string>();
    public ObservableCollection<string> SampleData
    {
        get
        {
            if (sampleData.Count <= 0)
            {
                sampleData.Add(@"Nintendo 64.png");
                sampleData.Add(@"Nintendo Famicom.png");
                sampleData.Add(@"Super Nintendo Entertainment System.png");
                sampleData.Add(@"Nintendo Entertainment System.png");
                sampleData.Add(@"Sony PlayStation.png");
            }
            return sampleData;
        }
    }

    private void Right_Click(object sender, RoutedEventArgs e)
    {
        var firstItem = SampleData.First();
        SampleData.Remove(firstItem);
        SampleData.Insert(SampleData.Count, firstItem);
    }

    private void Left_Click(object sender, RoutedEventArgs e)
    {
        var lastItem = SampleData.Last();
        SampleData.Remove(lastItem);
        SampleData.Insert(0, lastItem);
    }
}
 public static class ItemsControlExtensions
    {
        public static void ScrollToCenterOfView(this ItemsControl itemsControl, object item)
        {
            // Scroll immediately if possible
            if (!itemsControl.TryScrollToCenterOfView(item))
            {
                // Otherwise wait until everything is loaded, then scroll
                if (itemsControl is ListBox) ((ListBox)itemsControl).ScrollIntoView(item);
                itemsControl.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
                {
                    itemsControl.TryScrollToCenterOfView(item);
                }));
            }
        }

        private static bool TryScrollToCenterOfView(this ItemsControl itemsControl, object item)
        {
            // Find the container
            var container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as UIElement;
            if (container == null) return false;

            // Find the ScrollContentPresenter
            ScrollContentPresenter presenter = null;
            for (Visual vis = container; vis != null && vis != itemsControl; vis = VisualTreeHelper.GetParent(vis) as Visual)
                if ((presenter = vis as ScrollContentPresenter) != null)
                    break;
            if (presenter == null) return false;

            // Find the IScrollInfo
            var scrollInfo =
                !presenter.CanContentScroll ? presenter :
                presenter.Content as IScrollInfo ??
                FirstVisualChild(presenter.Content as ItemsPresenter) as IScrollInfo ??
                presenter;

            // Compute the center point of the container relative to the scrollInfo
            Size size = container.RenderSize;
            Point center = container.TransformToAncestor((Visual)scrollInfo).Transform(new Point(size.Width / 2, size.Height / 2));
            center.Y += scrollInfo.VerticalOffset;
            center.X += scrollInfo.HorizontalOffset;

            // Adjust for logical scrolling
            if (scrollInfo is StackPanel || scrollInfo is VirtualizingStackPanel)
            {
                double logicalCenter = itemsControl.ItemContainerGenerator.IndexFromContainer(container) + 0.5;
                Orientation orientation = scrollInfo is StackPanel ? ((StackPanel)scrollInfo).Orientation : ((VirtualizingStackPanel)scrollInfo).Orientation;
                if (orientation == Orientation.Horizontal)
                    center.X = logicalCenter;
                else
                    center.Y = logicalCenter;
            }

            // Scroll the center of the container to the center of the viewport
            if (scrollInfo.CanVerticallyScroll) scrollInfo.SetVerticalOffset(CenteringOffset(center.Y, scrollInfo.ViewportHeight, scrollInfo.ExtentHeight));
            if (scrollInfo.CanHorizontallyScroll) scrollInfo.SetHorizontalOffset(CenteringOffset(center.X, scrollInfo.ViewportWidth, scrollInfo.ExtentWidth));
            return true;
        }

        private static double CenteringOffset(double center, double viewport, double extent)
        {
            return Math.Min(extent - viewport, Math.Max(0, center - viewport / 2));
        }
        private static DependencyObject FirstVisualChild(Visual visual)
        {
            if (visual == null) return null;
            if (VisualTreeHelper.GetChildrenCount(visual) == 0) return null;
            return VisualTreeHelper.GetChild(visual, 0);
        }
    }