WPF холст и сетка - PullRequest
       23

WPF холст и сетка

4 голосов
/ 02 ноября 2009

У меня есть Grid, который представляет некоторые данные, и мне нужно Canvas, чтобы наложить поверх него, чтобы расположить некоторые строки. Canvas внутри себя UserControl.

Проблема в том, что Canvas и его содержимое должны автоматически изменять размер, когда Grid изменяет ширину и высоту.

Я добавил Canvas внутри ViewBox, но это не сработало. Когда Grid изменяет размер, Canvas не изменяет. Цель Canvas - наложить функциональность, подобную линейке, поверх сетки.

Ждем ваших решений.

EDIT

Я не могу использовать стиль в сетке для замены холста, потому что сетка показывает другую информацию, чем холст. Думайте об этом как о диаграмме, в которой есть столбцы столбцов разных размеров (в моем случае сетка), а дни - это линии в наложении (как диаграмма Ганта)

Мой код:

    taxCanvas = new TimeAxis();
    Grid.SetRowSpan(taxCanvas, GRightMain.RowDefinitions.Count);
    Grid.SetColumnSpan(taxCanvas, GRightMain.ColumnDefinitions.Count);

    Grid.SetColumn(taxCanvas, 0);
    Grid.SetRow(taxCanvas, 0);


    Grid.SetZIndex(taxCanvas, -1);

    taxCanvas.Height = GRight.ActualHeight;
    taxCanvas.Width = GRight.ActualWidth;

    GRightMain.Children.Add(taxCanvas);

TimeAxis - это мой пользовательский контроль на холсте, GRightMain - это сетка, в которой и мой холст, и сетка содержат содержимое (Gright) в одной строке и столбце.

Надеюсь, это поможет

Ответы [ 3 ]

4 голосов
/ 11 сентября 2013

Холст, безусловно, неправильный подход на мой взгляд.

Я настоятельно рекомендую поискать Adorners. Вы можете создать собственный рекламный элемент, чтобы сделать именно это.

Adorner - это "неинтерактивное окно", которое находится поверх всех элементов UIE. Он позволяет вам делать все что угодно (создавать элементы управления, рисовать объекты и т. Д.), Которые будут отображаться поверх самого элемента управления.

Изобразите деревянный журнальный столик с кусочком прозрачного стекла на нем. Если вы рисуете на прозрачном стекле, вы все равно видите сквозь журнальный столик. Единственное отличие состоит в том, что вы можете протянуть руку сквозь прозрачное стекло на кофейном столике и дотронуться до самого дерева.

Я ненавижу публиковать ссылки MSDN ... но ... эх. В этом случае это было бы хорошим началом:

http://msdn.microsoft.com/en-us/library/ms743737.aspx

EDIT:

Я быстро что-то бросил. Надеюсь, это поможет?

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:loc="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
  <Grid>
     <loc:GridWithRulerxaml></loc:GridWithRulerxaml>
     <Button Height="20" Width="50" >Click me</Button>
     <TextBox Width="150" Height="25" HorizontalAlignment="Left">This is a text box</TextBox>
  </Grid>
</Window>

UserControl:

<UserControl x:Class="WpfApplication1.GridWithRulerxaml"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
  <Grid>

  </Grid>
</UserControl>

КОД ПОЛЬЗОВАТЕЛЯ КОНТРОЛЯ:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace WpfApplication1
{
  /// <summary>
  /// Interaction logic for GridWithRulerxaml.xaml
  /// </summary>
  public partial class GridWithRulerxaml : UserControl
  {
    public GridWithRulerxaml()
    {
      InitializeComponent();

      //Loaded event is necessary as Adorner is null until control is shown.
      Loaded += GridWithRulerxaml_Loaded;

    }

    void GridWithRulerxaml_Loaded(object sender, RoutedEventArgs e)
    {
      var adornerLayer = AdornerLayer.GetAdornerLayer(this);
      var rulerAdorner = new RulerAdorner(this);
      adornerLayer.Add(rulerAdorner);
    }
  }
}

НАКОНЕЦ ОДЕЖДЫ СЕБЯ:

using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace WpfApplication1
{
  public class RulerAdorner : Adorner
  {
    private FrameworkElement element;
    public RulerAdorner(UIElement el) : base(el)
    {
      element = el as FrameworkElement;
    }

    protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
    {
      base.OnRender(drawingContext);

      double height = element.ActualHeight;
      double width = element.ActualWidth;

      double linesHorizontal = height/50;
      double linesVertical = width/50;

      var pen = new Pen(Brushes.RoyalBlue, 2) { StartLineCap = PenLineCap.Triangle, EndLineCap = PenLineCap.Triangle };

      int offset = 0;

      for (int i = 0; i <= linesVertical; ++i)
      {
        offset = offset + 50;
        drawingContext.DrawLine(pen, new Point(offset, 0), new Point(offset, height));
      }

      offset = 0;

      for (int i = 0; i <= linesHorizontal; ++i)
      {
        offset = offset + 50;
        drawingContext.DrawLine(pen, new Point(0, offset), new Point(width, offset));
      }
    }
  }
}

Если вы хотите, чтобы я подробнее рассказал о самом коде, дайте мне знать.

Я подтвердил, что это будет рисовать сетку поверх того, что находится на вашей главной странице. Вы все еще должны быть в состоянии взаимодействовать с тем, что находится внизу.

1 голос
/ 02 ноября 2009

Что вы пытаетесь сделать? Если вы просто хотите добавить линии сетки ко всей сетке, вы можете сделать это, установив стили , например, . В качестве альтернативы вы можете использовать Adorner s. Они там для украшения / украшения элементов на отдельном слое. Преимущество украшений в том, что, несмотря на то, что они находятся на отдельном слое, они синхронизируются (размер, положение, преобразование) с элементом, который они украшают.

1 голос
/ 02 ноября 2009

Вы можете использовать привязку, чтобы «связать» размер Canvas и размер Grid друг с другом. Поэтому, когда Grid изменяет размер, Canvas будет делать это слишком автоматически.

Также вы можете использовать Converter для привязки, которую вы должны вычислить и сместить как расстояние от границы.

Связывание в WPF - это всегда хорошая идея, поэтому убедитесь, что вы знаете основы его работы.

В любом случае вы всегда можете сделать это в коде (C # / VB) в Size-Event. Просто определите размер одного элемента управления и установите его для другого. Как получить свойство actualHeight таблицы и установить для него свойство height холста.

Может быть, это даст вам представление: http://blogs.msdn.com/bencon/archive/2006/05/10/594886.aspx или же http://www.switchonthecode.com/tutorials/wpf-tutorial-binding-converters

...