WinRT:ItemsPanel,为每个Item指定了xPos和yPos

时间:2014-12-19 07:57:22

标签: c# winrt-xaml itemscontrol

我对WinRT / C#/ XAML编程很陌生,所以请原谅这对你来说是一个简单的问题。

我想在某种背景(面板,画布,网格,你的名字)上安排一些图像(将来可以点击)。所以我可以使用像ListView等预定义的用户控件,但在我的情况下,我有一个特殊的标准:每个元素的x和y-Index应该从ViewModel派生。 (背景:我尝试创建一种"评分" - 应用程序,学生按照他们坐在教室前面的方式排列。点击学生图像的上部区域会增加等级,下方区域的点击会降低它。)

所以,我正在查看许多不同的教程和示例,但据我所知,在所有这些ItemsControl / ItemsPanel-Examples中,Items的排列由parent-element完成,即ItemsControl的。这样,我就不知道如何通过数据绑定来访问定位。

如果有人会如此善良并且发布或许只是一个想法,那么

之类的东西
public class data{
  public BitmapImage Image{get;set;}
  public String Name{get;set;}
  public int xIndex {get;set;}
  public int yIndex {get;set;}
}
收集在ObservableCollection中的

可以用上述方式显示(以及将来处理)吗?

提前谢谢

阿德里安

1 个答案:

答案 0 :(得分:1)

我找到了一种可行的方式,它不是最好的,但是通过这种方式,您可以覆盖项目的排列由父控件完成。

你的班级:

public class Data
{
    public BitmapImage Image { get; set; }
    public string Name { get; set; }
    public double xIndex { get; set; }
    public double yIndex { get; set; }
}

视图模型:

public class ViewModel


  {
        private readonly ObservableCollection<Data> images = new ObservableCollection<Data>();
        public ObservableCollection<Data> Images
        {
            get { return images; }
        }

        public ViewModel()
        {
            Images.Add(new Data
            {
                Image = new BitmapImage(new Uri("ms-appx:///../Assets/StoreLogo.scale-100.png")),
                Name = "Image1",
                xIndex = 50,
                yIndex = 50
            });

            Images.Add(new Data
            {
                Image = new BitmapImage(new Uri("ms-appx:///../Assets/SmallLogo.scale-100.png")),
                Name = "Image2",
                xIndex = 250,
                yIndex = 250
            });

            Images.Add(new Data
            {
                Image = new BitmapImage(new Uri("ms-appx:///../Assets/SplashScreen.scale-100.png")),
                Name = "Image3",
                xIndex = 500,
                yIndex = 500
            });
        }
    }

页:

<Page
    x:Class="App8.MainPage"
    DataContext="{Binding ViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App8"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="0 100 0 0">

        <ItemsControl ItemsSource="{Binding Images}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentPresenter x:Name="Test" Canvas.Left="{Binding xIndex}" Canvas.Top="{Binding yIndex}">
                        <StackPanel>
                            <TextBlock Text="{Binding Name}"/>
                            <Image Height="50" Source="{Binding Image}"/>
                        </StackPanel>
                    </ContentPresenter>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <local:MyCanvas />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Grid>
</Page>

您需要自己的ItemsPanelTemplate来覆盖排列。

public class MyCanvas : Canvas
{
    protected override Size ArrangeOverride(Size finalSize)
    {
        var children = this.GetDescendantsOfType<ContentPresenter>();

        foreach (var item in children)
        {
            var data = item.Content as Data;
            if (data != null)
            {
                Canvas.SetLeft(item, data.xIndex);
                Canvas.SetTop(item, data.yIndex);
            }
        }

        return base.ArrangeOverride(finalSize);
    }
}

GetDescendantsOfType是WinRT XAML Toolkit中VisualTreeHelperExtensions的一部分。

public static class VisualTreeHelperExtensions
{
    /// <summary>
    /// Gets the descendants of the given type.
    /// </summary>
    /// <typeparam name="T">Type of descendants to return.</typeparam>
    /// <param name="start">The start.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetDescendantsOfType<T>(this DependencyObject start) where T : DependencyObject
    {
        return start.GetDescendants().OfType<T>();
    }

    /// <summary>
    /// Gets the descendants.
    /// </summary>
    /// <param name="start">The start.</param>
    /// <returns></returns>
    public static IEnumerable<DependencyObject> GetDescendants(this DependencyObject start)
    {
        if (start == null)
        {
            yield break;
        }

        var queue = new Queue<DependencyObject>();

        var popup = start as Popup;

        if (popup != null)
        {
            if (popup.Child != null)
            {
                queue.Enqueue(popup.Child);
                yield return popup.Child;
            }
        }
        else
        {
            var count = VisualTreeHelper.GetChildrenCount(start);

            for (int i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(start, i);
                queue.Enqueue(child);
                yield return child;
            }
        }

        while (queue.Count > 0)
        {
            var parent = queue.Dequeue();

            popup = parent as Popup;

            if (popup != null)
            {
                if (popup.Child != null)
                {
                    queue.Enqueue(popup.Child);
                    yield return popup.Child;
                }
            }
            else
            {
                var count = VisualTreeHelper.GetChildrenCount(parent);

                for (int i = 0; i < count; i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    yield return child;
                    queue.Enqueue(child);
                }
            }
        }
    }
}