与列表框中的选择对齐有关的问题 [英] Issues with alignment with selection in a listbox

查看:77
本文介绍了与列表框中的选择对齐有关的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找创建一个矩形列表,这些矩形通过x,y坐标指定其位置,但是我发现图形的对齐方式存在问题.我正在使用带有自定义布局面板的列表框.

I'm looking at creating a list of rectangles that specify their location by an x,y coordinate, however I'm seeing an issue with the alignment of the graphics. I'm using a list box with a custom layout panel.

这是主窗口的XAML:

Here's the XAML for the main window:

<Window x:Class="WpfFunkyPanel.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfFunkyPanel"
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <system:Double x:Key="barWidth">30</system:Double>
    <system:Double x:Key="trackHeight">24</system:Double>
    <Style x:Key="PatternGridStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="local:GridPanel.Bar" Value="{Binding Bar}"/>
        <Setter Property="local:GridPanel.Track" Value="{Binding Track}"/>
    </Style>
</Window.Resources>
<Grid>
    <ListBox ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource PatternGridStyle}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <local:GridPanel VerticalAlignment="Top" BarWidth="{StaticResource barWidth}" TrackHeight="{StaticResource trackHeight}">
                    <local:GridPanel.Background>
                        <DrawingBrush TileMode="Tile" ViewboxUnits="Absolute" ViewportUnits="Absolute">
                            <DrawingBrush.Viewbox>
                                <Rect X="0" Y="0" Width="{StaticResource barWidth}" Height="{StaticResource trackHeight}"/>
                            </DrawingBrush.Viewbox>
                            <DrawingBrush.Viewport>
                                <Rect X="1" Y="0" Width="{StaticResource barWidth}" Height="{StaticResource trackHeight}"/>
                            </DrawingBrush.Viewport>
                            <DrawingBrush.Drawing>
                                <GeometryDrawing Brush="LightGray">
                                    <GeometryDrawing.Pen>
                                        <Pen Brush="Black" Thickness="1"/>
                                    </GeometryDrawing.Pen>
                                    <GeometryDrawing.Geometry>
                                        <PathGeometry>
                                            <PathFigure IsFilled="True">
                                                <LineSegment>
                                                    <LineSegment.Point>
                                                        <Point X="{StaticResource barWidth}" Y="0"/>
                                                    </LineSegment.Point>
                                                </LineSegment>
                                                <LineSegment>
                                                    <LineSegment.Point>
                                                        <Point X="{StaticResource barWidth}" Y="{StaticResource trackHeight}"/>
                                                    </LineSegment.Point>
                                                </LineSegment>
                                                <LineSegment>
                                                    <LineSegment.Point>
                                                        <Point X="0" Y="{StaticResource trackHeight}"/>
                                                    </LineSegment.Point>
                                                </LineSegment>
                                                <LineSegment/>
                                            </PathFigure>
                                        </PathGeometry>
                                    </GeometryDrawing.Geometry>
                                </GeometryDrawing>
                            </DrawingBrush.Drawing>
                        </DrawingBrush>
                    </local:GridPanel.Background>
                </local:GridPanel>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid Margin="0,1,0,1">
                    <Rectangle Fill="Gray" Width="28" Height="22"></Rectangle>
                    <TextBlock Text="{Binding Text}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>
</Window>

这是网格面板:

using System;

namespace WpfFunkyPanel
{
using System.Windows;
using System.Windows.Controls;

public class GridPanel : Panel
{
    public static readonly DependencyProperty BarProperty = DependencyProperty.RegisterAttached(
        "Bar",
        typeof(int),
        typeof(GridPanel));

    public static readonly DependencyProperty TrackProperty = DependencyProperty.RegisterAttached(
        "Track",
        typeof(int),
        typeof(GridPanel));

    public static readonly DependencyProperty BarWidthProperty = DependencyProperty.Register(
        "BarWidth",
        typeof(double),
        typeof(GridPanel),
        new FrameworkPropertyMetadata(
            28.0,
            FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));

    public static readonly DependencyProperty TrackHeightProperty = DependencyProperty.Register(
        "TrackHeight",
        typeof(double),
        typeof(GridPanel),
        new FrameworkPropertyMetadata(
            24.0,
            FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));

    public static int GetBar(DependencyObject obj)
    {
        return (int)obj.GetValue(BarProperty);
    }

    public static void SetBar(DependencyObject obj, int value)
    {
        obj.SetValue(BarProperty, value);
    }

    public static int GetTrack(DependencyObject obj)
    {
        return (int)obj.GetValue(TrackProperty);
    }

    public static void SetTrack(DependencyObject obj, int value)
    {
        obj.SetValue(TrackProperty, value);
    }

    public GridPanel()
    {

    }

    protected override Size MeasureOverride(Size availableSize)
    {
        Size size = new Size();

        foreach (UIElement child in InternalChildren)
        {
            int bar = GetBar(child);
            int track = GetTrack(child);

            double width = (bar + 1) * BarWidth;
            double height = (track + 1) * TrackHeight;

            size.Width = Math.Max(size.Width, width);
            size.Height = Math.Max(size.Height, height);
        }

        return size;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        foreach (UIElement child in InternalChildren)
        {
            int bar = GetBar(child);
            int track = GetTrack(child);

            Rect rect = new Rect(bar * BarWidth, track * TrackHeight, BarWidth, TrackHeight);
            child.Arrange(rect);
        }

        return finalSize;
    }

    public double BarWidth
    {
        get
        {
            return (double)this.GetValue(BarWidthProperty);
        }

        set
        {
            SetValue(BarWidthProperty, value);
        }
    }

    public double TrackHeight
    {
        get
        {
            return (double)this.GetValue(TrackHeightProperty);
        }

        set
        {
            SetValue(TrackHeightProperty, value);
        }
    }
}
}

这是图案项目:

namespace WpfFunkyPanel
{
public class PatternItem
{
    private readonly int bar;

    private readonly int track;

    private readonly string text;

    public PatternItem(int bar, int track, string text)
    {
        this.bar = bar;
        this.track = track;
        this.text = text;
    }

    public int Bar
    {
        get
        {
            return bar;
        }
    }

    public int Track
    {
        get
        {
            return track;
        }
    }

    public string Text
    {
        get
        {
            return text;
        }
    }
}
}

这是集合视图模型:

namespace WpfFunkyPanel
{
using System.Collections.ObjectModel;

public class PatternContainer
{
    private int bars;

    private int tracks;

    private ObservableCollection<PatternItem> items; 

    public PatternContainer()
    {
        bars = 32;
        tracks = 24;
        items = new ObservableCollection<PatternItem>();
    }

    public void Add(PatternItem item)
    {
        items.Add(item);
    }

    public int Bars
    {
        get
        {
            return bars;
        }
    }

    public int Tracks
    {
        get
        {
            return tracks;
        }
    }

    public ObservableCollection<PatternItem> Items
    {
        get
        {
            return items;
        }
    }
}
}

最后,后面的主窗口代码:

Finally, the main window code behind:

使用System.Windows;

using System.Windows;

namespace WpfFunkyPanel
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var container = new PatternContainer();

        for (int bar = 0; bar < 16; bar++)
        {
            container.Add(new PatternItem(bar, 0, "A" + (bar + 1).ToString()));
        }

        container.Add(new PatternItem(3, 2, "C4"));
        container.Add(new PatternItem(5, 5, "G6"));

        DataContext = container;
    }
}
}

这是它的外观,并选择了一个矩形:

Here's what it looks like, with a rectangle selected:

问题是蓝色的选择框向左偏移.另外,为了使物体对齐,我不得不将视口设置为1,0,w,h而不是我期望的0,0,w,h.

The problem is the selection box in blue is offset to the left. Also, in order to get things to align, I had to set the viewport to 1,0,w,h not 0,0,w,h as I would have expected.

推荐答案

找到了一个解决方案-创建我自己的控件GridControl(从Selector派生)和GridItemControl(ContentControl),现在一切都变得有意义了.

Found a solution - create my own controls GridControl (derived from Selector) and GridItemControl (ContentControl) and now it all makes sense.

这是我的GridControlItem:

Here's my GridControlItem:

public class GridControlItem : ContentControl
{
    public static readonly DependencyProperty BarProperty = DependencyProperty.Register(
        "Bar",
        typeof(int),
        typeof(GridControlItem),
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public static readonly DependencyProperty TrackProperty = DependencyProperty.Register(
        "Track",
        typeof(int),
        typeof(GridControlItem),
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public static readonly DependencyProperty PickedProperty = DependencyProperty.Register(
        "Picked",
        typeof(bool),
        typeof(GridControlItem),
        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public int Bar
    {
        get
        {
            return (int)this.GetValue(BarProperty);
        }

        set
        {
            SetValue(BarProperty, value);
        }
    }

    public int Track
    {
        get
        {
            return (int)this.GetValue(TrackProperty);
        }

        set
        {
            SetValue(TrackProperty, value);
        }
    }

    public bool Picked
    {
        get
        {
            return (bool)this.GetValue(PickedProperty);
        }

        set
        {
            SetValue(PickedProperty, value);
        }
    }

    static GridControlItem()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(GridControlItem), new FrameworkPropertyMetadata(typeof(GridControlItem)));
    }

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);

        if (e.ChangedButton == MouseButton.Left)
        {
            this.Picked = true;
            e.Handled = true;
        }
    }
}

我特意使用"Picked"而不是"IsSelected"来确保其有效.

I deliberately used "Picked" instead of "IsSelected" to make sure this works.

现在使用GridControl:

Now the GridControl:

public class GridControl : Selector
{
    static GridControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(GridControl), new FrameworkPropertyMetadata(typeof(GridControl)));
    }

    protected override DependencyObject GetContainerForItemOverride()
    {
        return new GridControlItem();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return (item is GridControlItem);
    }
}

和Generic.xaml:

and the Generic.xaml:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PatternControlLibrary"
xmlns:system="clr-namespace:System;assembly=mscorlib">

<system:Double x:Key="barWidth">30</system:Double>
<system:Double x:Key="trackHeight">24</system:Double>

<Style TargetType="{x:Type local:GridControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:GridControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
                        <ItemsPresenter />
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <local:GridPanel VerticalAlignment="Top" BarWidth="{StaticResource barWidth}" TrackHeight="{StaticResource trackHeight}">
                    <local:GridPanel.Background>
                        <DrawingBrush TileMode="Tile" ViewboxUnits="Absolute" ViewportUnits="Absolute">
                            <DrawingBrush.Viewbox>
                                <Rect X="0" Y="0" Width="{StaticResource barWidth}" Height="{StaticResource trackHeight}"/>
                            </DrawingBrush.Viewbox>
                            <DrawingBrush.Viewport>
                                <Rect X="0" Y="0" Width="{StaticResource barWidth}" Height="{StaticResource trackHeight}"/>
                            </DrawingBrush.Viewport>
                            <DrawingBrush.Drawing>
                                <GeometryDrawing Brush="LightGray">
                                    <GeometryDrawing.Pen>
                                        <Pen Brush="Black" Thickness="1"/>
                                    </GeometryDrawing.Pen>
                                    <GeometryDrawing.Geometry>
                                        <PathGeometry>
                                            <PathFigure IsFilled="True">
                                                <LineSegment>
                                                    <LineSegment.Point>
                                                        <Point X="{StaticResource barWidth}" Y="0"/>
                                                    </LineSegment.Point>
                                                </LineSegment>
                                                <LineSegment>
                                                    <LineSegment.Point>
                                                        <Point X="{StaticResource barWidth}" Y="{StaticResource trackHeight}"/>
                                                    </LineSegment.Point>
                                                </LineSegment>
                                                <LineSegment>
                                                    <LineSegment.Point>
                                                        <Point X="0" Y="{StaticResource trackHeight}"/>
                                                    </LineSegment.Point>
                                                </LineSegment>
                                                <LineSegment/>
                                            </PathFigure>
                                        </PathGeometry>
                                    </GeometryDrawing.Geometry>
                                </GeometryDrawing>
                            </DrawingBrush.Drawing>
                        </DrawingBrush>
                    </local:GridPanel.Background>
                </local:GridPanel>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type local:GridControlItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:GridControlItem}">
                <Border x:Name="Border">
                    <ContentPresenter />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="Picked" Value="True">
                        <Setter TargetName="Border" Property="Background" Value="Red"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="local:GridPanel.Bar" Value="{Binding Bar}"/>
    <Setter Property="local:GridPanel.Track" Value="{Binding Track}"/>
</Style>
</ResourceDictionary>

这是MainWindow.xaml:

Here's the MainWindow.xaml:

<Window x:Class="WpfFunkyPanel.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    xmlns:cc="clr-namespace:PatternControlLibrary;assembly=PatternControlLibrary"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>

    <DataTemplate x:Key="dataItemTemplate">
        <Grid>
            <Rectangle Fill="LightPink" Width="28" Height="22"/>
            <TextBlock Text="{Binding Text}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        </Grid>
    </DataTemplate>
</Window.Resources>

<Grid>
    <cc:GridControl 
        ItemsSource="{Binding Items}"
        ItemTemplate="{StaticResource dataItemTemplate}"/>
</Grid>
</Window>

这篇关于与列表框中的选择对齐有关的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆