WPF列表框可以绕过另一个组件吗?

WPF列表框可以绕过另一个组件吗?,wpf,listbox,Wpf,Listbox,我需要在窗口右侧固定一个文本块,在其中设置注释,窗口的其余部分可以是一个列表框,其中填充了可选项。我的问题是,便笺可以是可见的,也可以是不可见的,可选择的项目应该像在Word中一样,将图像和环绕文本设置为“方形” 示例: 已添加 我创建了一个自定义UniformGrid,添加了一个属性NoteRowToSkip,用于在左侧的最后一列中表示要跳过的行。我覆盖ArrangeOverride并添加了所需的跳过行为。 调试看起来值是正确的,但具有与UniformGrid相同的行为 publi

我需要在窗口右侧固定一个文本块,在其中设置注释,窗口的其余部分可以是一个列表框,其中填充了可选项。我的问题是,便笺可以是可见的,也可以是不可见的,可选择的项目应该像在Word中一样,将图像和环绕文本设置为“方形”

示例:

已添加

我创建了一个自定义UniformGrid,添加了一个属性NoteRowToSkip,用于在左侧的最后一列中表示要跳过的行。我覆盖ArrangeOverride并添加了所需的跳过行为。 调试看起来值是正确的,但具有与UniformGrid相同的行为

    public class UniformNoteWrapGrid : Panel
    {
        private int m_Rows;
        private int m_Columns;

        public static readonly DependencyProperty NoteRowToSkipProperty = DependencyProperty.Register(nameof(NoteRowToSkip), typeof(int), typeof(UniformGrid), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsMeasure), ValidateNoteRowToSkip);
        private static bool ValidateNoteRowToSkip(object o)
        {
            return (int)o >= 0;
        }
        public int Columns
        {
            get => (int)GetValue(ColumnsProperty);
            set => SetValue(ColumnsProperty, value);
        }

        public static readonly DependencyProperty ColumnsProperty =
            DependencyProperty.Register(
                "Columns",
                typeof(int),
                typeof(UniformGrid),
                new FrameworkPropertyMetadata(
                    0,
                    FrameworkPropertyMetadataOptions.AffectsMeasure),
                ValidateColumns);

        private static bool ValidateColumns(object o)
        {
            return (int)o >= 0;
        }

        public int Rows
        {
            get => (int)GetValue(RowsProperty);
            set => SetValue(RowsProperty, value);
        }

        public static readonly DependencyProperty RowsProperty =
            DependencyProperty.Register("Rows", typeof(int),
                typeof(UniformGrid),
                new FrameworkPropertyMetadata(
                    0,
                    FrameworkPropertyMetadataOptions.AffectsMeasure),
                ValidateRows);

        private static bool ValidateRows(object o)
        {
            return (int)o >= 0;
        }

        public int NoteRowToSkip
        {
            get => (int)GetValue(NoteRowToSkipProperty);
            set => SetValue(NoteRowToSkipProperty, value);
        }

        protected override Size MeasureOverride(Size constraint)
        {
            UpdateComputedValues();

            var childConstraint = new Size(constraint.Width / m_Columns, constraint.Height / m_Rows);
            double maxChildDesiredWidth = 0.0;
            double maxChildDesiredHeight = 0.0;

            for (int i = 0, count = InternalChildren.Count; i < count; ++i)
            {
                var child = InternalChildren[i];

                child.Measure(childConstraint);
                var childDesiredSize = child.DesiredSize;

                if (maxChildDesiredWidth < childDesiredSize.Width)
                    maxChildDesiredWidth = childDesiredSize.Width;

                if (maxChildDesiredHeight < childDesiredSize.Height)
                    maxChildDesiredHeight = childDesiredSize.Height;
            }

            return new Size(maxChildDesiredWidth * m_Columns, maxChildDesiredHeight * m_Rows);
        }

        protected override Size ArrangeOverride(Size arrangeSize)
        {
            var childBounds = new Rect(0, 0, arrangeSize.Width / m_Columns, arrangeSize.Height / m_Rows);
            double xStep = childBounds.Width;
            double xBound = arrangeSize.Width - 1.0;
            var row = 1;
            var column = 1;

            foreach (UIElement child in InternalChildren)
            {
                child.Arrange(childBounds);

                if (child.Visibility == Visibility.Collapsed)
                    continue;

                childBounds.X += xStep;
                column++;
                var testXBound = xBound;
                if (IsCellForNote(row, column))
                    testXBound -= childBounds.Height;

                if (!(childBounds.X >= testXBound))
                    continue;

                childBounds.Y += childBounds.Height;
                childBounds.X = 0;
                row++;
                column = 1;
            }

            return arrangeSize;
        }

        private bool IsCellForNote(int row, int column)
        {
            if (row > NoteRowToSkip)
                return true;

            return column != Columns;
        }

        private void UpdateComputedValues()
        {
            m_Columns = Columns;
            m_Rows = Rows;

            //if (FirstColumn >= m_Columns)
            //  FirstColumn = 0;

            if (m_Rows != 0 && m_Columns != 0)
                return;

            int nonCollapsedCount = 0;

            for (int i = 0, count = InternalChildren.Count; i < count; ++i)
            {
                var child = InternalChildren[i];
                if (child.Visibility != Visibility.Collapsed)
                    nonCollapsedCount++;
            }

            if (nonCollapsedCount == 0)
                nonCollapsedCount = 1;

            if (m_Rows == 0)
            {
                if (m_Columns > 0)
                    m_Rows = (nonCollapsedCount + (m_Columns - 1)) / m_Columns;
                else
                {
                    m_Rows = (int)Math.Sqrt(nonCollapsedCount);
                    if ((m_Rows * m_Rows) < nonCollapsedCount)
                        m_Rows++;

                    m_Columns = m_Rows;
                }
            }
            else if (m_Columns == 0)
                m_Columns = (nonCollapsedCount + (m_Rows - 1)) / m_Rows;
        }
    }
公共类UniformNoteWrapGrid:面板
{
私人国际货币单位行;
私有int m_列;
public static readonly dependencProperty NoteRowToSkipProperty=dependencProperty.Register(name of(NoteRowToSkip)、typeof(int)、typeof(UniformGrid)、new FrameworkPropertyMetadata(0,FrameworkPropertyMetadata options.AffectsMeasure)、ValidateNoterRowtoSkip);
私有静态bool validateNotRowtoskip(对象o)
{
返回值(int)o>=0;
}
公共int列
{
get=>(int)GetValue(ColumnsProperty);
set=>SetValue(ColumnsProperty,value);
}
公共静态只读依赖项属性列属性=
从属属性。寄存器(
“栏目”,
类型(int),
类型(UniformGrid),
新框架属性元数据(
0,
FrameworkPropertyMetadataOptions.AffectsMeasure),
验证电子柱);
私有静态bool ValidateColumns(对象o)
{
返回值(int)o>=0;
}
公共整数行
{
get=>(int)GetValue(RowsProperty);
set=>SetValue(RowsProperty,value);
}
公共静态只读依赖项属性行属性=
DependencyProperty.寄存器(“行”,类型(int),
类型(UniformGrid),
新框架属性元数据(
0,
FrameworkPropertyMetadataOptions.AffectsMeasure),
ValidateRows);
私有静态bool ValidateRows(对象o)
{
返回值(int)o>=0;
}
公共int NoteRowToSkip
{
get=>(int)GetValue(NoteRowToSkipProperty);
set=>SetValue(NoteRowToSkipProperty,value);
}
受保护的覆盖尺寸测量覆盖(尺寸约束)
{
updateComputerdValues();
var childConstraint=新大小(constraint.Width/m_列,constraint.Height/m_行);
双maxChildDesiredWidth=0.0;
双maxChildDesiredHeight=0.0;
for(int i=0,count=InternalChildren.count;i=testXBound))
继续;
childBounds.Y+=childBounds.Height;
childBounds.X=0;
行++;
列=1;
}
返回安排大小;
}
私有bool IsCellForNote(int行,int列)
{
如果(行>注释行)
返回true;
返回列!=列;
}
私有void updateComputerdValues()
{
m_列=列;
m_行=行;
//如果(第一列>=m_列)
//第一列=0;
如果(m_行!=0和m_列!=0)
返回;
int noncollecsedCount=0;
for(int i=0,count=InternalChildren.count;i0)
m_行=(非合并计数+(m_列-1))/m_列;
其他的
{
m_Rows=(int)Math.Sqrt(nonCollapsedCount);
if((m_行*m_行)
知道我的代码中有什么不起作用吗

已解决 public class UniformNoteWrapGrid : Panel { private int m_Rows; private int m_Columns; public static readonly DependencyProperty NoteRowToSkipProperty = DependencyProperty.Register(nameof(NoteRowToSkip), typeof(int), typeof(UniformGrid), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsMeasure), ValidateNoteRowToSkip); private static bool ValidateNoteRowToSkip(object o) { return (int)o >= 0; } public int Columns { get => (int)GetValue(ColumnsProperty); set => SetValue(ColumnsProperty, value); } public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register( "Columns", typeof(int), typeof(UniformGrid), new FrameworkPropertyMetadata( 0, FrameworkPropertyMetadataOptions.AffectsMeasure), ValidateColumns); private static bool ValidateColumns(object o) { return (int)o >= 0; } public int Rows { get => (int)GetValue(RowsProperty); set => SetValue(RowsProperty, value); } public static readonly DependencyProperty RowsProperty = DependencyProperty.Register("Rows", typeof(int), typeof(UniformGrid), new FrameworkPropertyMetadata( 0, FrameworkPropertyMetadataOptions.AffectsMeasure), ValidateRows); private static bool ValidateRows(object o) { return (int)o >= 0; } public int NoteRowToSkip { get => (int)GetValue(NoteRowToSkipProperty); set => SetValue(NoteRowToSkipProperty, value); } protected override Size MeasureOverride(Size constraint) { UpdateComputedValues(); var childConstraint = new Size(constraint.Width / m_Columns, constraint.Height / m_Rows); double maxChildDesiredWidth = 0.0; double maxChildDesiredHeight = 0.0; for (int i = 0, count = InternalChildren.Count; i < count; ++i) { var child = InternalChildren[i]; child.Measure(childConstraint); var childDesiredSize = child.DesiredSize; if (maxChildDesiredWidth < childDesiredSize.Width) maxChildDesiredWidth = childDesiredSize.Width; if (maxChildDesiredHeight < childDesiredSize.Height) maxChildDesiredHeight = childDesiredSize.Height; } return new Size(maxChildDesiredWidth * m_Columns, maxChildDesiredHeight * m_Rows); } protected override Size ArrangeOverride(Size arrangeSize) { var childBounds = new Rect(0, 0, arrangeSize.Width / m_Columns, arrangeSize.Height / m_Rows); double xStep = childBounds.Width; double xBound = arrangeSize.Width - 1.0; var row = 1; var column = 1; foreach (UIElement child in InternalChildren) { child.Arrange(childBounds); if (child.Visibility == Visibility.Collapsed) continue; childBounds.X += xStep; column++; var testXBound = xBound; if (IsCellForNote(row, column)) testXBound -= xStep; if (!(childBounds.X >= testXBound)) continue; childBounds.Y += childBounds.Height; childBounds.X = 0; row++; column = 1; } return arrangeSize; } private bool IsCellForNote(int row, int column) { if (row > NoteRowToSkip) return false; return column == Columns; } private void UpdateComputedValues() { m_Columns = Columns; m_Rows = Rows; //if (FirstColumn >= m_Columns) // FirstColumn = 0; if (m_Rows != 0 && m_Columns != 0) return; int nonCollapsedCount = 0; for (int i = 0, count = InternalChildren.Count; i < count; ++i) { var child = InternalChildren[i]; if (child.Visibility != Visibility.Collapsed) nonCollapsedCount++; } if (nonCollapsedCount == 0) nonCollapsedCount = 1; if (m_Rows == 0) { if (m_Columns > 0) m_Rows = (nonCollapsedCount + (m_Columns - 1)) / m_Columns; else { m_Rows = (int)Math.Sqrt(nonCollapsedCount); if ((m_Rows * m_Rows) < nonCollapsedCount) m_Rows++; m_Columns = m_Rows; } } else if (m_Columns == 0) m_Columns = (nonCollapsedCount + (m_Rows - 1)) / m_Rows; } }
<ItemsControl x:Name="panel">
        <ItemsControl.Resources>
            <DataTemplate DataType="{x:Type local:NoteItem}">
                <TextBlock HorizontalAlignment="Right" TextWrapping="Wrap" Width="50" Height="150" Margin="10" 
                           Text="{Binding Text}" Background="LightBlue">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock">
                            <Setter Property="Visibility" Value="Visible"/>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Visible}" Value="False" >
                                    <Setter Property="Visibility" Value="Collapsed"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
            </DataTemplate>
            <DataTemplate DataType="{x:Type local:ListItem}">
                <TextBlock TextWrapping="Wrap" Width="50" Height="50" Margin="10" Text="{Binding Text}" Background="LightGray"/>
            </DataTemplate>
        </ItemsControl.Resources>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
public class Item
{
    public string Text { get; set; }
}

public class NoteItem:Item
{
    public bool Visible{ get; set; }
}

public class ListItem : Item
{
}

public partial class MainWindow : Window
{

    ObservableCollection<Item> list = new ObservableCollection<Item>();

    public MainWindow()
    {
        InitializeComponent();

        NoteItem note = new NoteItem { Text = "This is a note", Visible = true };
        list.Add(note);
        for(int i=0;i<20; i++)
            list.Add(new ListItem { Text = "This is a list item" });
        panel.ItemsSource = list;
    }
}