Озарение: Canvas не определяет свой размер по размеру дочернего элемента.
Второй целью этой задачи было создать компонент, который сможет не только справится с выше озвученной проблемой, но и сможет принимать новые параметры. Понятным языком — необходимо сделать доступным в xaml разметке компонента пользовательские свойства, через которые можно передавать параметры новому компоненту.
Озарение: Для создания пользовательских свойств компонента, доступных в xaml разметки необходимо использовать объект свойств зависимостей public static readonly DependencyProperty.
И так, постановка задачи:
1) Любой ценой разместить Canvas в ScrollViewer;
2) Реализовать эту задачу, как чисто в xaml так и чисто в C# (создав компонент)
3) Привести пример использование DependencyProperty
Замечание: Добавлять Canvas в ScrollViewer напрямую не удастся, вместо этого в ScrollViewer будет вложен Grid, в нем что угодно, в том числе Canvas. Все прочее что необходимо будет добавить добавляем в Grid:
Реализация на xaml:
<ScrollViewer HorizontalScrollBarVisibility="Auto" Width="auto" Height="auto" Grid.Column="0" Grid.Row="1">
<ScrollViewer.Content>
<!-- Объект Canvas вложенный В объект ScrollViewer примет размер Scroll viewer и не будет учитывать
рамер объектов размещенных в Canvasе!! - поэтому используется Grid, а в нем Canvas -->
<Grid Width="auto" Height="auto" >
<!-- Смастерим просмотрщик: Размер Gridа будет под размер изображения-->
<Image x:Name="loadedImage" Width="auto" Height="auto">
<Image.RenderTransform>
<CompositeTransform ScaleX="1" ScaleY="1"/><!-- Задел для масштабирования-->
</Image.RenderTransform>
</Image>
<!-- Если не все дочерние эл-ты в Grid разместить в одной ячейки то они могут идти как два слоя -->
<Canvas Background="Transparent" >
<!-- Поверх Image будет прозрачный Холст, а на нем кнопка (можно заменить на что, нибудь другое) -->
<Button Content="It s Canvas" Canvas.Left="100" Canvas.Top="100"/>
<!-- Вообщим Canvas будет такого-же размера как и Image -->
</Canvas>
</Grid>
</ScrollViewer.Content>
</ScrollViewer>Syhi-подсветка кода
Реализация компонента на C#:<ScrollViewer.Content>
<!-- Объект Canvas вложенный В объект ScrollViewer примет размер Scroll viewer и не будет учитывать
рамер объектов размещенных в Canvasе!! - поэтому используется Grid, а в нем Canvas -->
<Grid Width="auto" Height="auto" >
<!-- Смастерим просмотрщик: Размер Gridа будет под размер изображения-->
<Image x:Name="loadedImage" Width="auto" Height="auto">
<Image.RenderTransform>
<CompositeTransform ScaleX="1" ScaleY="1"/><!-- Задел для масштабирования-->
</Image.RenderTransform>
</Image>
<!-- Если не все дочерние эл-ты в Grid разместить в одной ячейки то они могут идти как два слоя -->
<Canvas Background="Transparent" >
<!-- Поверх Image будет прозрачный Холст, а на нем кнопка (можно заменить на что, нибудь другое) -->
<Button Content="It s Canvas" Canvas.Left="100" Canvas.Top="100"/>
<!-- Вообщим Canvas будет такого-же размера как и Image -->
</Canvas>
</Grid>
</ScrollViewer.Content>
</ScrollViewer>Syhi-подсветка кода
// Небольшой класс реализующий возможность простых манипуляций изображений
// В данном случае возможность просмотра изображения превышающего размер окна
public class ImageManipulate : ContentControl
{
// Добавляем произвольное свойство к создаваемому компоненту - исходное изображение
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(Image),typeof(ImageManipulate), null);
//Дополнительное свойство позволяющее принимать canvas как параметр в xaml разметке
public static readonly DependencyProperty CanvasInsideProperty =
DependencyProperty.Register("CanvasInside", typeof(Canvas), typeof(ImageManipulate), null);
private double _imageWidth; // Ширина оригинального изображения
private double _imageHeight; // Высота оригинального изображения
private Image _image; // Изображение для возможных манипуляций
private ScrollViewer viewerBox;
private Grid mainGridContainer;
//Свойство которое и осуществляет прием и передачу изображения
public Image Source
{
get { return (Image)GetValue(SourceProperty); }
set
{
SetValue(SourceProperty, value);
_image = value;//Кэшируем изображение
_imageWidth = _image.Width;
_imageHeight = _image.Height;
this.mainGridContainer.Children.Add(this._image);//Добавляем изображение в Grid
}
}
public Canvas CanvasInside
{
get { return (Canvas)GetValue(CanvasInsideProperty); }
set
{
SetValue(CanvasInsideProperty, value);
this.mainGridContainer.Children.Add(value);
}
}
public ImageManipulate()
{
this.mainGridContainer = new Grid();
viewerBox = new ScrollViewer() { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto };
viewerBox.Content = this.mainGridContainer;// Создаем объект контейнера с "ползунками" и добаляем в него Грид
this.Content = viewerBox;
}
}Syhi-подсветка кода
Его ре инкарнация в xaml разметке:// В данном случае возможность просмотра изображения превышающего размер окна
public class ImageManipulate : ContentControl
{
// Добавляем произвольное свойство к создаваемому компоненту - исходное изображение
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(Image),typeof(ImageManipulate), null);
//Дополнительное свойство позволяющее принимать canvas как параметр в xaml разметке
public static readonly DependencyProperty CanvasInsideProperty =
DependencyProperty.Register("CanvasInside", typeof(Canvas), typeof(ImageManipulate), null);
private double _imageWidth; // Ширина оригинального изображения
private double _imageHeight; // Высота оригинального изображения
private Image _image; // Изображение для возможных манипуляций
private ScrollViewer viewerBox;
private Grid mainGridContainer;
//Свойство которое и осуществляет прием и передачу изображения
public Image Source
{
get { return (Image)GetValue(SourceProperty); }
set
{
SetValue(SourceProperty, value);
_image = value;//Кэшируем изображение
_imageWidth = _image.Width;
_imageHeight = _image.Height;
this.mainGridContainer.Children.Add(this._image);//Добавляем изображение в Grid
}
}
public Canvas CanvasInside
{
get { return (Canvas)GetValue(CanvasInsideProperty); }
set
{
SetValue(CanvasInsideProperty, value);
this.mainGridContainer.Children.Add(value);
}
}
public ImageManipulate()
{
this.mainGridContainer = new Grid();
viewerBox = new ScrollViewer() { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto };
viewerBox.Content = this.mainGridContainer;// Создаем объект контейнера с "ползунками" и добаляем в него Грид
this.Content = viewerBox;
}
}Syhi-подсветка кода
<!-- xmlns:local="clr-namespace:FotoDocDemo1;assembly=FotoDocDemo1" - ссылаемся на пространство имен
в котором находится класс ImageManipulate-->
<local:ImageManipulate Grid.Row="1" Width="auto" Height="auto">
<!-- Свойство Source: -->
<local:ImageManipulate.Source>
<Image Source="img/avstria.jpg" Width="auto" Height="auto"/>
</local:ImageManipulate.Source>
<!-- Свойство CanvasInside-->
<local:ImageManipulate.CanvasInside>
<Canvas Width="auto" Height="auto">
<Button Content="Click" Canvas.Left="200" Canvas.Top="200"/>
</Canvas>
</local:ImageManipulate.CanvasInside>
</local:ImageManipulate>Syhi-подсветка кода
в котором находится класс ImageManipulate-->
<local:ImageManipulate Grid.Row="1" Width="auto" Height="auto">
<!-- Свойство Source: -->
<local:ImageManipulate.Source>
<Image Source="img/avstria.jpg" Width="auto" Height="auto"/>
</local:ImageManipulate.Source>
<!-- Свойство CanvasInside-->
<local:ImageManipulate.CanvasInside>
<Canvas Width="auto" Height="auto">
<Button Content="Click" Canvas.Left="200" Canvas.Top="200"/>
</Canvas>
</local:ImageManipulate.CanvasInside>
</local:ImageManipulate>Syhi-подсветка кода