Мне кажется, что вы не хотите использовать 2D-массив. Вместо этого вы хотите использовать один массив и обращаться к нему, как если бы он был 2D-массивом. Это правильно?
Это означает, что вам нужно применить простую математику к вашей задаче.
Исходя из вашего описания, ваша 2D-таблица имеет одинаковую высоту и ширину, поэтому height = width.
Если вы хотите получить индекс
index = column + width * row
Если вы хотите получить x и y на основе индекса:
column = index % width;
row = index / width;
Примечание: я не тестировал это как код еще. Кроме того, дайте мне знать, если это помогло.
Я решил эту проблему, поместив изображение в рамку с его свойством ClipToBounds, установленным в True. RenderTransformOrigin на изображении затем устанавливается на 0,5,0,5, поэтому изображение начнет масштабироваться по центру изображения. Для RenderTransform также устанавливается TransformGroup, содержащая ScaleTransform и TranslateTransform.
Затем я обработал событие MouseWheel на изображении для реализации масштабирования
private void image_MouseWheel(object sender, MouseWheelEventArgs e)
{
var st = (ScaleTransform)image.RenderTransform;
double zoom = e.Delta > 0 ? .2 : -.2;
st.ScaleX += zoom;
st.ScaleY += zoom;
}
Для обработки панорамирования первое, что я сделал, было обработало событие MouseLeftButtonDown на событии Чтобы сохранить изображение и записать его местоположение, я также сохраняю текущее значение TranslateTransform, которое обновляется для реализации панорамирования.
Point start;
Point origin;
private void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
image.CaptureMouse();
var tt = (TranslateTransform)((TransformGroup)image.RenderTransform)
.Children.First(tr => tr is TranslateTransform);
start = e.GetPosition(border);
origin = new Point(tt.X, tt.Y);
}
Затем я обработал событие MouseMove, чтобы обновить TranslateTransform.
private void image_MouseMove(object sender, MouseEventArgs e)
{
if (image.IsMouseCaptured)
{
var tt = (TranslateTransform)((TransformGroup)image.RenderTransform)
.Children.First(tr => tr is TranslateTransform);
Vector v = start - e.GetPosition(border);
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
}
}
Наконец, don ' не забудьте отпустить захват мыши.
private void image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
image.ReleaseMouseCapture();
}
Что касается ручек выбора для изменения размера, то это может быть выполнено с помощью рекламного устройства, см. эту статью для получения дополнительной информации.
Мой образец London Underground делает это, хотя с картой, а не со статическим изображением.
Попробуйте этот элемент управления масштабированием: http://wpfextensions.codeplex.com
Использование элемента управления очень просто, ссылка на сборку wpfextensions:
<wpfext:ZoomControl>
<Image Source="..."/>
</wpfext:ZoomControl>
Полосы прокрутки не поддерживается в данный момент. (Это будет в следующем выпуске, который будет доступен через одну или две недели).
Ответ был опубликован выше, но не был полным. вот завершенная версия:
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MapTest.Window1"
x:Name="Window"
Title="Window1"
Width="1950" Height="1546" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Controls="clr-namespace:WPFExtensions.Controls;assembly=WPFExtensions" mc:Ignorable="d" Background="#FF000000">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="52.92"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="1" Name="border">
<Image Name="image" Source="map3-2.png" Opacity="1" RenderTransformOrigin="0.5,0.5" />
</Border>
</Grid>
Code Behind
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace MapTest
{
public partial class Window1 : Window
{
private Point origin;
private Point start;
public Window1()
{
InitializeComponent();
TransformGroup group = new TransformGroup();
ScaleTransform xform = new ScaleTransform();
group.Children.Add(xform);
TranslateTransform tt = new TranslateTransform();
group.Children.Add(tt);
image.RenderTransform = group;
image.MouseWheel += image_MouseWheel;
image.MouseLeftButtonDown += image_MouseLeftButtonDown;
image.MouseLeftButtonUp += image_MouseLeftButtonUp;
image.MouseMove += image_MouseMove;
}
private void image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
image.ReleaseMouseCapture();
}
private void image_MouseMove(object sender, MouseEventArgs e)
{
if (!image.IsMouseCaptured) return;
var tt = (TranslateTransform) ((TransformGroup) image.RenderTransform).Children.First(tr => tr is TranslateTransform);
Vector v = start - e.GetPosition(border);
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
}
private void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
image.CaptureMouse();
var tt = (TranslateTransform) ((TransformGroup) image.RenderTransform).Children.First(tr => tr is TranslateTransform);
start = e.GetPosition(border);
origin = new Point(tt.X, tt.Y);
}
private void image_MouseWheel(object sender, MouseWheelEventArgs e)
{
TransformGroup transformGroup = (TransformGroup) image.RenderTransform;
ScaleTransform transform = (ScaleTransform) transformGroup.Children[0];
double zoom = e.Delta > 0 ? .2 : -.2;
transform.ScaleX += zoom;
transform.ScaleY += zoom;
}
}
}
У меня есть пример полного проекта wpf с использованием этого кода на моем веб-сайте: Запишите приложение для заметок .
Чтобы получить профессиональный элемент управления масштабированием для WPF, ознакомьтесь с ZoomPanel .
Он не бесплатный, но очень прост в использовании и имеет множество функций - анимированное масштабирование и панорамирование, поддержка ScrollViewer, поддержка колеса мыши, включенный ZoomController (с перемещением, увеличением, уменьшением, масштабированием прямоугольника, кнопками сброса) . Он также поставляется с множеством примеров кода.
Все, что вам нужно для масштабирования относительно положения мыши, это:
var position = e.GetPosition(image1);
image1.RenderTransformOrigin = new Point(position.X / image1.ActualWidth, position.Y / image1.ActualHeight);
@Anothen и @ Number8 - Класс Vector недоступен в Silverlight, поэтому для его работы нам просто нужно сохранить запись последней обнаруженной позиции последний раз, когда было вызвано событие MouseMove, и сравните две точки, чтобы найти разницу; затем настройте преобразование.
XAML:
<Border Name="viewboxBackground" Background="Black">
<Viewbox Name="viewboxMain">
<!--contents go here-->
</Viewbox>
</Border>
Код программной части:
public Point _mouseClickPos;
public bool bMoving;
public MainPage()
{
InitializeComponent();
viewboxMain.RenderTransform = new CompositeTransform();
}
void MouseMoveHandler(object sender, MouseEventArgs e)
{
if (bMoving)
{
//get current transform
CompositeTransform transform = viewboxMain.RenderTransform as CompositeTransform;
Point currentPos = e.GetPosition(viewboxBackground);
transform.TranslateX += (currentPos.X - _mouseClickPos.X) ;
transform.TranslateY += (currentPos.Y - _mouseClickPos.Y) ;
viewboxMain.RenderTransform = transform;
_mouseClickPos = currentPos;
}
}
void MouseClickHandler(object sender, MouseButtonEventArgs e)
{
_mouseClickPos = e.GetPosition(viewboxBackground);
bMoving = true;
}
void MouseReleaseHandler(object sender, MouseButtonEventArgs e)
{
bMoving = false;
}
Также обратите внимание, что вам не нужны TransformGroup или коллекция для реализации панорамирования и масштабирования; вместо этого CompositeTransform сделает это с меньшими хлопотами.
Я почти уверен, что это действительно неэффективно с точки зрения использования ресурсов, но, по крайней мере, это работает :)