fbpx
× Share your code snippets, screen shots etc. here

Why I like WPF, but not XAML or how to build a custom control in X#

  • Wolfgang Riedmann
  • Wolfgang Riedmann's Avatar Topic Author
  • Away
More
1 year 11 months ago #1 by Wolfgang Riedmann
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:
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

and then the control itself:
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

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:
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

I hope this code gives you an idea how to implement own controls!
Attachments:

Please Log in or Create an account to join the conversation.

More
1 year 11 months ago #2 by Phil Hepburn
Oh! - I see, yesterday's Windows have become tomorrows Doors !?

Nice one Wolfgang ;-0)

Cheers,
Phil.

Please Log in or Create an account to join the conversation.

  • Wolfgang Riedmann
  • Wolfgang Riedmann's Avatar Topic Author
  • Away
More
1 year 11 months ago #3 by Wolfgang Riedmann
Hi Phil,

one of my largest customers builds windows (real ones, mostly in wood, but some also in PVC), and part of his business are also house entrance doors.
And for them I need to build a door configuration software. Fortunately I have selected X# and WPF based on the MVVM pattern to build this application.
WPF gives really a LOT of options for graphical interfaces - practically there seem to be very few limits for the imagination of the programmer.
And strange enough: it is hard to find informations how to work without XAML, but if you find them, WPF shows its real power, and code is much more understandable than XAML - it is enough to look at the InitilizeComponents() method of my control class.

Hopefully I can show you this application in Cologne (have yet to book, but I will come there of course).

Wolfgang

Please Log in or Create an account to join the conversation.

More
1 year 11 months ago #4 by Phil Hepburn
Hi Wolfgang,

An interesting project indeed.

Yes, I look forward to seeing it demoed at the conference.

Good Luck and fingers crossed for future developments on this app.

Best Regards,
Phil.

Please Log in or Create an account to join the conversation.