Так как близится создание еще одного контрола для WinGym – Draggable ListBox (имеющийся на 8-ой версии не завелся), решил перевести статью про создание контрола (с хорошего сайта)
В этой статье я собираюсь показать, как создать простой свой контрол используя Сильверлайт для ВП7 (для 8-ой актуально). Обычно кастомные контролы можно создавать как контролы, которые наследуются от каких-нибудь существующих контролов и расширяют их функционал.
Кастомные контролы – это благо (можно грузить сборкой куда надо). Все контролы, которые юзаются в Сильверлайте (Button, TextBlock, ListBox) и UserControl также являются кастомными. Обычно кастомные наследуются от Control, ItemsControl, ContentControl и так далее.
Для того, чтобы лучше понять UI модель Сильверлайта и разницу между Custom Control и User Control глядите предыдущий пост – (User Control vs Custom Control in Silverlight for WP7 – может тоже переведу)
В этой статье мы собираемся создать очень простой кастомный контрол: MyCustomControl, который наследуется от ContentControl и встраивает IconSource свойство без добавления каких либо VisualStates. Мы сконцентрируемся на минимальных требованиях, которые вам надо выполнить, чтобы создать кастом контрол.
Для начала создадим кастом контрол по шагам:
1. Создаем Windows Phone Class Library в Visual Studio:
Это сгенерирует класс по имени “Class1.cs”. Это класс, который мы будем использовать для того, чтобы реализовать кастом контрол. Сменим имя на “MyCustomControl.cs”
2. Мы создадим простой кастом контрол, наследуемый от ContentControl, в котором будет dependency property – IconSource. IconSource будет использоваться для того, чтобы позволить юзерам добавлять различные картинки в наш контрол. Добавьте следующий код в MyCustomControl.cs:
public class MyCustomControl : ContentControl
{
public static readonly DependencyProperty IconSourceProperty =
DependencyProperty.Register("IconSource", typeof(ImageSource), typeof(MyCustomControl), null);
public MyCustomControl()
{
DefaultStyleKey = typeof(MyCustomControl);
}
public ImageSource IconSource
{
get { return base.GetValue(IconSourceProperty) as ImageSource; }
set { base.SetValue(IconSourceProperty, value); }
}
}
(Использовал плагин для LiveWriter для кода) :)
Заметка: Больше инфы по поводу DependencyProperty можно найти в MSDN.
Заметка: DefaultStyleKey гетит или сетит ключ, который ссылается на дефолтный стиль для контрола
Заметка: В более сложных сценариях, когда вам надо получить ссылку на какую-то часть ControlTemplate обязательно перегрузить OnApplyTemplate. Этот метод вызывается перед тем как отобразить UI элемент. OnApplyTemplate зачастую более подходящее место для работы с настройкой дерева отображения (visual tree), чем событие Loaded. В Silverlight событие Loaded может возникнуть перед тем как применять шаблон, а отсюда, вы можете не суметь изменить дерево отображения меняя шаблон в обработчике Loaded.
Например:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
ContentPresenter presenter = this.GetTemplateChild("ContentContainer") as ContentPresenter;
}
<ContentPresenterx:Name="ContentContainer"Content="{TemplateBinding Content}"ContentTemplate="{TemplateBinding ContentTemplate}"Margin="{TemplateBinding Padding}"/>
3. Следующий шаг – создать папку по имени “Themes”
Заметка: Имя папки – важно!
4. После этого добавьте файл generic.xaml в папку
На данный момент в Silverlight для WP7 нет подходящего темплейта Visual Studio для создания XAML или ResourceDictionary как файла в проекте (уже есть вроде). Для того, чтобы добавить generic.xaml, создайте новый класс, да просто переименуйте.
Заметка: Имя важно!
Заметка: Очень важно чтобы вы поставили Build Action в Resource. Это необходимо для того, чтобы убедиться, что шаблон запакован в ту же сборку, что и контрол, иначе шаблон не будет применяться.
5. Добавьте следующий код разметки в ваш generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
<Style>
</Style>
</ResourceDictionary>
Заметка: Вот хорошие ссылки по данной теме:
В нашем случае код выглядит так:<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
xmlns:local="clr-namespace:CustomControlSample">
<Style TargetType="local:MyCustomControl">
<Setter Property="Background" Value="YellowGreen"/>
<Setter Property="IconSource" Value="/CustomControlSample;component/Themes/icon.png"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyCustomControl">
<Border BorderBrush="White" BorderThickness="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{TemplateBinding IconSource}" Stretch="None"/>
<Border Background="{TemplateBinding Background}" Grid.Column="1">
<ContentPresenter
x:Name="ContentContainer"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="{TemplateBinding Padding}"/>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Мы добавили Image, ContentPresenter, TemplateBinding для важных свойств. Когда контрол наследуется от ContentControl это означает, что у него есть свойство Content, которое разработчики могут использовать для кастомайза содержимого. ContentPresenter может визуализировать любой XAML, назначенный свойству Content.
Заметка: TemplateBinding связывает значение свойства в шаблоне контрола со значением проперти в шаблонизированном контроле.
Заметка: Мы определяем дефолтное значение кастомного контрола используя Style Setters.
Заметка: Нет x:Key атрибута, потому что дефолтный стиль контрола определяется TargetType
Заметка: Мы добавили icon.png в наш проект и положили в папку Themes.
7. Все, финиш.
Давайте используем контрол где-нибудь.
Ссылаемся на сборку CustomControlSample. После этого определяем неймспейс. И вуаля<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
Вот картинки - <myControl:MyCustomControl Height="100" Width="200" Content="Content"/>
<TextBlock Text="Second Example" Margin="20"/>
<myControl:MyCustomControl Height="100" Width="400" Background="Transparent" IconSource="fl.jpg">
<myControl:MyCustomControl.Content>
<StackPanel>
<TextBlock Text="Some Text Content Here"/>
<Button Content="Test Button"/>
</StackPanel>
</myControl:MyCustomControl.Content>
</myControl:MyCustomControl>
</StackPanel>
Исходный код - http://www.windowsphonegeek.com/upload/articles/CustomControlSample.zip
Pockets — are the slots on the roulette wheel the place the ball falls. All bets on the roulette desk have the same expected web loss per greenback guess . But 1xbet the returns on some bets are more variable than on others. You can go for the massive bucks by selecting these bets, lengthy as|so lengthy as} you are prepared for chance of|the potential of|the potential for} shedding big. An empirical histogram of these shows the chances of completely different outcomes of your \$1 guess on red. Why are the desk limits relevant in the Martingale strategy?
ОтветитьУдалить