Why I like WPF, but not XAML or how to build a custom control in X#
Posted: Fri Jan 20, 2017 9:02 am
With VO background and the willingness to subclass controls, WPF opens an entire new world of GUI creation.
There is no control that does what you like? Then create your own!
Please take this bitmap button with full databinding as sample (with XAML and DataTemplates it would also be possible, but not as clear as in pure code).
The data class:
and then the control itself:
In my code, this control is only a part of a product selection, and I use this control in a WrapPanel for selection, in pure MVVM style.
Of course, if someone is interested, I can supply also the code for the items control.
The use is very simple:
I hope this code gives you an idea how to implement own controls!
There is no control that does what you like? Then create your own!
Please take this bitmap button with full databinding as sample (with XAML and DataTemplates it would also be possible, but not as clear as in pure code).
The data class:
Code: Select all
class ImageText
constructor( cKey as string, cImageName as string, cText as string )
self:Key := cKey
self:ImageName := cImageName
self:Text := cText
return
method ToString() as string
return self:Text
property ImageName as string auto
property Text as string auto
property Key as string auto
end class
Code: Select all
using System.Windows
using System.Windows.Controls
using System.Windows.Media.Imaging
using System.Diagnostics
class ImageTextButton inherit Button
protect _oImage as Image
protect _oTextBlock as TextBlock
protect _oImageText as ImageText
public static initonly ImageTextProperty as DependencyProperty
static constructor()
ImageTextButton.ImageTextProperty := DependencyProperty.Register( "ImageText", ;
TypeOf( ImageText ), TypeOf( ImageTextButton ), ;
UIPropertyMetadata{ null, PropertyChangedCallback{ ImageTextPropertyChanged } } )
return
constructor()
self:InitializeComponent()
return
method InitializeComponent() as void
local oGrid as Grid
local oRowDefinition as RowDefinition
oGrid := Grid{}
oGrid:ColumnDefinitions:Add( ColumnDefinition{} )
oGrid:RowDefinitions:Add( RowDefinition{} )
oRowDefinition := RowDefinition{}
oRowDefinition:Height := GridLength.Auto
oGrid:RowDefinitions:Add( oRowDefinition )
_oImage := Image{}
Grid.SetRow( _oImage, 0 )
Grid.SetColumn( _oImage, 0 )
oGrid:Children:Add( _oImage )
_oTextBlock := TextBlock{}
_oTextBlock:HorizontalAlignment := HorizontalAlignment.Center
_oTextBlock:VerticalAlignment := VerticalAlignment.Stretch
_oTextBlock:TextWrapping := TextWrapping.Wrap
Grid.SetRow( _oTextBlock, 1 )
Grid.SetColumn( _oTextBlock, 0 )
oGrid:Children:Add( _oTextBlock )
self:Content := oGrid
return
static method ImageTextPropertyChanged( d as DependencyObject, e as DependencyPropertyChangedEventArgs ) as void
local oImageTextButton as ImageTextButton
local oImageText as ImageText
oImageTextButton := ( ImageTextButton ) d
oImageText := ( ImageText ) e:NewValue
oImageTextButton:_ImageText := oImageText
return
property ImageText as ImageText
set
self:SetValue( ImageTextButton.ImageTextProperty, value )
end set
get
return ( ImageText ) self:GetValue( ImageTextButton.ImageTextProperty )
end get
end property
property _BitmapName as string
set
local oBitmapImage as BitmapImage
local cBitmapName as string
cBitmapName := value
if System.IO.File.Exists( cBitmapName )
oBitmapImage := BitmapImage{}
oBitmapImage:BeginInit()
oBitmapImage:UriSource := Uri{ cBitmapName }
oBitmapImage:EndInit()
_oImage:Source := oBitmapImage
endif
end set
get
return "" // cannot retrieve name from image
end get
end property
property _ImageText as ImageText
set
_oImageText := value
self:_BitmapName := _oImageText:ImageName
self:_TextBlock := _oImageText:Text
self:Name := _oImageText:Key
end set
get
return _oImageText
end get
end property
property _TextBlock as string
set
_oTextBlock:Text := value
end set
get
return ( string ) _oTextBlock:Text
end get
end property
end class
Of course, if someone is interested, I can supply also the code for the items control.
The use is very simple:
Code: Select all
oImageTexts := ObservableCollection<ImageText>{}
foreach oProduktConfig as ProduktConfig in oProduktConfigs
cImageName := oProduktConfig:ProduktImage:ToLower()
cImage := Path.Combine( cImagePath, cImageName + ".png" )
if ! File.Exists( cImage )
cImage := Path.Combine( cImagePath, cImageName + ".jpg" )
endif
oImageTexts:Add( ImageText{ oProduktConfig:Name, cImage, oProduktConfig:Description } )
next
self:ItemSource := oImageTexts