2014-10-24 5 views
1

Я ищу создание списка прямоугольников, которые определяют их местоположение по координате x, y, однако я вижу проблему с выравниванием графики. Я использую окно списка с настраиваемой панелью.Проблемы с выравниванием с выбором в списке

Вот 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: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; 
     } 
    } 
} 
} 

И наконец, код главного окна позади:

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; 
    } 
} 
} 

Вот как это выглядит, с прямоугольником выбранным:

Selection Alignment

Проблема заключается в окно выбора синим смещена влево. Кроме того, для того, чтобы добиться выравнивания, мне нужно было установить окно просмотра 1,0, w, h не 0,0, w, h, как я и ожидал.

ответ

0

Нашли решение - создайте мои собственные элементы управления GridControl (производные от селектора) и GridItemControl (ContentControl), и теперь все это имеет смысл.

Вот мой 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; 
     } 
    } 
} 

Я намеренно использовал "поднято" вместо "IsSelected", чтобы убедиться, что это работает.

Теперь 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:

<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:

<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> 
Смежные вопросы