c# - 为 Windows Phone 8 创建两列、垂直堆叠的列控件

标签 c# wpf windows-phone-8 custom-controls itemscontrol

这可能是一个相当长且复杂的问题。首先让我说我正在使用 C# 和 XAML 进行开发。我想创建一个堆叠以下模板的控件:

_____________
|           |
| Text      |
| Image     |
| More Text |
|___________|

对于一系列项目,在两列中,如下所示:

______ ______
|    | |    |
| 1  | | 2  |
|____| |    |
|    | |____|
| 3  | |    |
|    | | 4  |
|    | |____|
|____| |    |
|    | | 5  |
| 6  | |    |
|    |

请注意,它们首先按高度排序,然后从左到右排序。

作为一个两列网格,每列网格中都有一个垂直堆栈面板,这相对简单。

对我来说,这是一系列项目的表示,因此将其呈现为继承自 ItemsControl 的控件是有意义的。

我该怎么做?设置 ItemTemplate 似乎很明显,其他一切都让我不知所措。

最佳答案

我认为我们应该使用 ListBox 并更改 ListBox 的 ItemsPanel。我们自定义一个面板为 ItemsPanel,定义 column 属性 并覆盖 MeasureOverrideArrangeOverride 方法。

代码如下:

using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace TravelHelper_WP8
{
    public class CustomPanel : Panel
    {
        public CustomPanel()
        {
            /**default 2 columns**/
            ColumnCount = 2;
            columnHeight = new double[ColumnCount];
            this.UseLayoutRounding = true;
        }

        static double[] columnHeight;

        public int ColumnCount
        {
            get { return (int)this.GetValue(ColumnCountProperty); }
            set { this.SetValue(ColumnCountProperty, value); }
        }

        public static DependencyProperty ColumnCountProperty = DependencyProperty.Register("ColumnCount", typeof(int), typeof(CustomPanel), new PropertyMetadata(new PropertyChangedCallback((o, e) =>
        {
            columnHeight = new double[(int)e.NewValue];
            if (o == null || e.NewValue == e.OldValue)
                return;
            o.SetValue(ColumnCountProperty, e.NewValue);
        })));

        protected override Size MeasureOverride(Size availableSize)
        {
            int indexY = this.Children.Count / ColumnCount;
            if (this.Children.Count % ColumnCount > 0) indexY++;
            int flagY = 0;
            Size resultSize = new Size(0, 0);
            #region<---- Measure Value

            for (int i = 0; i < indexY; i++)//Column
            {
                if (i == indexY - 1)
                {
                    int residual = Children.Count - i * ColumnCount;
                    if (Children.Count <= ColumnCount)
                    {
                        residual = Children.Count;
                    }

                    for (int h = 0; h < residual; h++)
                    {
                        Children[ColumnCount * flagY + h].Measure(availableSize);
                        resultSize.Width = (Children[ColumnCount * flagY + h].DesiredSize.Width) * ColumnCount;
                        columnHeight[h] += Children[ColumnCount * flagY + h].DesiredSize.Height;
                    }
                }
                else
                {
                    for (int y = 0; y < ColumnCount; y++)
                    {
                        Children[ColumnCount * flagY + y].Measure(availableSize);
                        resultSize.Width = (Children[ColumnCount * flagY + y].DesiredSize.Width) * ColumnCount;
                        columnHeight[y] += Children[ColumnCount * flagY + y].DesiredSize.Height;
                    }
                    flagY++;
                }
            }
            #endregion

            resultSize.Height = columnHeight.Max();
            return resultSize;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            for (int i = 0; i < columnHeight.Count(); i++)
            {
                columnHeight[i] = 0;
            }
            int indexY = this.Children.Count / ColumnCount;
            if (this.Children.Count % ColumnCount > 0) indexY++;
            int flagY = 0;
            double flagX = 0;

            #region<------Layout
            for (int i = 0; i < indexY; i++)//Column
            {
                finalSize.Width = (Children[i].DesiredSize.Width) * ColumnCount;
                if (i == indexY - 1)
                {
                    flagX = 0;
                    int residual = Children.Count - i * ColumnCount;
                    if (Children.Count <= ColumnCount)
                    {
                        residual = Children.Count;
                    }
                    for (int h = 0; h < residual; h++)
                    {
                        Children[ColumnCount * i + h].Arrange(new Rect(new Point(flagX, columnHeight[h]), Children[ColumnCount * i + h].DesiredSize));
                        columnHeight[h] += Children[ColumnCount * flagY + h].DesiredSize.Height;
                        flagX += Children[ColumnCount * i + h].DesiredSize.Width;
                    }
                }
                else
                {
                    for (int y = 0; y < ColumnCount; y++)
                    {
                        Children[ColumnCount * flagY + y].Arrange(new Rect(new Point(flagX, columnHeight[y]), Children[ColumnCount * i + y].DesiredSize));
                        columnHeight[y] += Children[ColumnCount * flagY + y].DesiredSize.Height;
                        flagX += Children[ColumnCount * flagY + y].DesiredSize.Width;
                    }
                    flagX = 0; flagY++;
                }
            }

            #endregion

            return finalSize;
        }
    }
}

关于c# - 为 Windows Phone 8 创建两列、垂直堆叠的列控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21842395/

相关文章:

c# - 切开声音效果/静音的开始

c# - 当 ViewModel 设置为 null 时,使用 ReactiveUI Bind 方法将绑定(bind)设置为 null

c# - 将 shared_ptr 与托管语言引用进行比较

c# - 使用 C# 如何将 RGB 转换为 YCrCb 以及将 YCrCb 转换为 RGB

c# - FluentribbonTabItem 在设计器中不可见?

c# - 带有自定义 header 的 Windows Phone 8 Http 请求

c# - 异步运行任何 C# 方法。可能的?

wpf - 如何使用 Textbox.Style 应用 StaticResource

c# - 公开 MVVM 中内置的用户控件的属性

windows-phone-8 - Windows Phone 8 后台代理仅在使用调试版本时运行(似乎不在发布版本上运行)