【问题标题】:WinRT: ItemsPanel with specified xPos und yPos for each ItemWinRT:ItemsPanel 为每个项目指定 xPos 和 yPos
【发布时间】:2014-12-19 17:52:56
【问题描述】:

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

我想在某种背景(面板、画布、网格等等)上安排大量图像(将来可以点击)。所以我可以使用预定义的用户控件,如 ListView 等,但就我而言,我有一个特殊的标准:每个元素的 x 和 y 索引应该从 ViewModel 派生。 (背景:我尝试创建一种“评分”应用程序,学生在教室中以坐在我面前的方式排列。单击学生图像的上部区域可提高成绩,单击较低的区域会减少它。)

所以,我浏览了许多不同的教程和示例,但据我所知,在所有这些 ItemsControl/ItemsPanel-Examples 中,Items 的排列是由父元素完成的,即项目控制。那样的话,我看不到如何通过数据绑定来访问定位。

如果有人这么好心,也许只是一个想法,像这样的东西

public class data{
  public BitmapImage Image{get;set;}
  public String Name{get;set;}
  public int xIndex {get;set;}
  public int yIndex {get;set;}
}

,收集在 ObservableCollection 中,是否可以按上述方式显示(并在将来处理)?

提前谢谢你

阿德里安

【问题讨论】:

    标签: c# winrt-xaml itemscontrol


    【解决方案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);
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 嘿,这看起来确实是一个很有前途的方法。我刚刚对其进行了测试,看起来它可以满足我的需求。感谢您快速详细的回复!
    猜你喜欢
    • 2021-05-03
    • 2018-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 2020-03-31
    • 2021-03-02
    • 1970-01-01
    相关资源
    最近更新 更多