1_
Declarative vs. procedural design
Those who use WinForms know that when a Form gets created, its appearance is defined in CSharp code in
InitializeComponent() method located in *.Designer.cs file. If you examine the method you will see that all controls
are built in sequence. This is true for Java as well
Those who are familiar with Delphi know that each form has a definition file that does not contain code, but declaration of elements with properties like position, width, heigth, title etc. This is called declarative definition.
WPF introduces annother format for declarative definition, XAML.
C# partial class Form1 { private void InitializeComponent() { this.textBox1 = new System.Windows.Forms.TextBox(); // // textBox1 // this.textBox1.Location = new System.Drawing.Point(32, 272); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(100, 22); this.textBox1.TabIndex = 2; } private System.Windows.Forms.TextBox textBox1; }
Those who are familiar with Delphi know that each form has a definition file that does not contain code, but declaration of elements with properties like position, width, heigth, title etc. This is called declarative definition.
WPF introduces annother format for declarative definition, XAML.
XAML <Window x:Class="Fundamentals.Binding.DataContext.PersonsWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="PersonsWindow" Height="300" Width="300"> <Grid> <TextBox Text="Hello" Height="23" Width="120" /> </Grid> </Window>There is still C# code behind in .xaml.cs file
C# namespace Fundamentals.Binding.DataContext { public partial class PersonsWindow : Window { public PersonsWindow() { InitializeComponent(); } } }Visual Studio designer supports design with XAML only.
2_
Layout types/controls
As todays devices may have very different screen resolution, from cell phone to smart TV, WPF provides also
another concepts, similar to web concepts, how to position controls in window.
(MSDN)
Grid - Grid with row and colums, similar HTML table StackPanel - Like grid without columns when Orientation=Vertical. When Orientation=Horizontal - only columns, no rows. WrapPanel - Like StackPanel, but if controls cannot be fit into the width of the panel, new row will be created. Canvas - XY coordinates DockPanel - allows component docking TabPanel - container for multiple tabs
3_
Describe logical tree
The same can be achieved by using Children property of FrameworkElement class or calling FindName().
XAML <Window> <StackPanel> <Button Content="Click on me" /> </StackPanel> </Window>
- Resolves Static and Dynamic resources
The same can be achieved by using Children property of FrameworkElement class or calling FindName().
4_
Describe visual tree
Button appears visible to user only because a Buttom template was applied to the Button
and the template is rendered on the screen. The template consist of border and content.
VisualTreeHelper provides methods that can be used to:
- examine Visaul Tree like GetParent() or GetChild()
- provide information regarding graphical appearace like GetOPacity(), GetTransform() etc.
VisualTreeHelper provides methods that can be used to:
- examine Visaul Tree like GetParent() or GetChild()
- provide information regarding graphical appearace like GetOPacity(), GetTransform() etc.
5_
How XAML designer loads binaries and how to keep it working
XAML designer does not use assemblies from the output folder, but it copies the assembly with the visual class that should present,
e.g window, and some classes on which the window depends into ShadowCache
C:\Users\>user<\AppData\Local\Microsoft\VisualStudio\12.0\Designer\ShadowCache\2cmmxtb2.ihv\uc04afqt.15c
It may cause a problem if a class used in the visual control loads data from an external file and the file is not available. It such case, in order to allow the designer to work, it is necessary that the code loading e.g. data from an external file does not throw exception, but rather returns empty result.
It may cause a problem if a class used in the visual control loads data from an external file and the file is not available. It such case, in order to allow the designer to work, it is necessary that the code loading e.g. data from an external file does not throw exception, but rather returns empty result.
6_
Create one way binding for Person data
With one way binding example below the data in the view is set upon creation.
When user modifies the data in the view, new values are updated in the model.
Model
C# class Person { public string PName { get; set; } public string PHeight{ get; set; } }View
XAML
<Window x:Class="Fundamentals.Binding.DataContext.PersonsWindow"
... >
<Grid>
<TextBox Text="{Binding PName}" Margin="12,20,0,0" />
<TextBox Text="{Binding PHeight}" Name="textBox2" />
</Grid>
</Window>
ViewModel
C# public partial class PersonsWindow : Window { private Person _dataSource; public PersonsWindow() { _dataSource = new Person(); _dataSource.PName = "Zbynek"; _dataSource.PHeight = "190"; DataContext = _dataSource; InitializeComponent(); } }
7_
Create two way binding for Person data
With one way binding, when the data in the model got updated, the change was not visible in the view.
In order to achieve that, it is ncecessary to setup 2 was binding.
It requires the model to implement INotifyPropertyChanged interface in the model.
Model
When user changes the datacontext value like ViewModel
Model
C# class Person : INotifyPropertyChanged { public string PName { get; set; } private double _pHeight; public double PHeight { get { return _pHeight; } set { if (value != _pHeight) { _pHeight = value; PropertyChanged(this, new PropertyChangedEventArgs("PHeight")); } } } public event PropertyChangedEventHandler PropertyChanged = delegate { }; }View and ViewModel remain the same as for 1 way binding.
When user changes the datacontext value like ViewModel
C# public partial class PersonsWindow : Window { ... private void btnIncrement_Click(object sender, RoutedEventArgs e) { ((Person)this.DataContext).PHeight += 1; } }With 2 way binding the value in UI will be updated when it gets changed in the model.
8_
Create data template for Person class
View
XAML <Window x:Class="Fundamentals.Binding.DataContext_Template.PersonsWindow" ... > <Window.Resources> <DataTemplate DataType="{x:Type loc:Person}"> <Grid> <TextBox Text="{Binding PName}" Name="textBox1" ... /> <TextBox Text="{Binding PHeight}" Name="textBox2" ... /> </Grid> </DataTemplate> </Window.Resources> <Grid> <ContentControl Content="{Binding}"/> </Grid> </Window>
9_
Display list of people in ListBox
ViewModel
C# public partial class PersonsWindow : Window { private ObservableCollection<Person> _dataSource; public PersonsWindow() { _dataSource = new ObservableCollection<Person>(); _dataSource.Add(new Person { PName = "Zbynek", PHeight = 190}); _dataSource.Add(new Person { PName = "Adrian", PHeight = 130 }); DataContext = _dataSource; InitializeComponent(); } }The it is necessary to bind ItemSource property of the ListBox to the data source that is represented as ObservableCollection. View
XAML <Window ... xmlns:loc="clr-namespace:Fundamentals.Binding.DataContext_Collection" > <Window.Resources> <DataTemplate DataType="{x:Type loc:Person}"> <Grid> <TextBox Text="{Binding PName}" ... /> <TextBox Text="{Binding PHeight}" ... /> </Grid> </DataTemplate> </Window.Resources> <Grid> <ListBox ItemsSource="{Binding}" /> </Grid> </Window>
10_
Master detail
For demonstration of Master detail view the Person class (model)
will be extened by ToString() method.
Model
View
Model
C# class Person : INotifyPropertyChanged { public string PName { ... } public double PHeight { ... } public override string ToString() { return PName + " " + Convert.ToString(PHeight); } ... }When user selects an item in ListBox then will be content represented by the return value of Person.ToString() method will be displayed in the TextBox.
View
XAML <Window ... xmlns:loc="clr-namespace:Fundamentals.Binding.DataContext_MasterDetail" > <Grid > <ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" ... > <ListBox.ItemTemplate> <DataTemplate DataType="{x:Type loc:Person}" > <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding PName}"/> <TextBlock Text="{Binding PHeight}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <!-- display selected item: using '/' below ensures that selected item is used {Binding / } => ToString() of selected object (person) is used {Binding / PName} => Name of selected object (person) is used --> <TextBlock Text="{Binding / }" ... /> </Grid> </Window>
11_
Define default value when binding fails
C# <TextBox Text="{Binding Name, FallbackValue='Not found'}" />
12_
How to show null value and how to write it back to database
XAML <TextBox Text="{Binding MyValue, TargetNullValue=''}" />It can be set a text value as, that will be presented to user and if if user write it down, WPF will write null back to model.
C# <TextBox Text="{Binding Name, TargetNullValue='Null value'}" />
13_
How could be source object used for binding referenced
Source object for Binding can be specified, if needed, witt he following attributes:
Only one of the properties can be set on binding
Source
Use source when you want bind to something else as DataContext
- Source
- RelativeSource
- ElementName
Only one of the properties can be set on binding
Source
Use source when you want bind to something else as DataContext
XAML <TextBox Text="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}" />It is possible to avoid using Source by assigning DataContext for the control directly
XAML <TextBox DataContext="{x:Static SystemParameters.WorkArea}" Text="{Binding Width}" />ElementName
XAML <TextBox Name="textBox3" BorderBrush="Red" /> <TextBox BorderBrush="{Binding ElementName=textBox3, Path=BorderBrush}" />
14_
Determine binding in code
textBox1 is type of TextBox
C#
System.Windows.Data.Binding binding = BindingOperations.GetBinding(textBox1, TextBox.TextProperty);
string path = binding.Path.Path;
string elementName = binding.ElementName;
object source = myBinding.Source;
15_
Set binding binding in code (IsEnabled of Label bound to IsEnabled of targeted TextBox)
C# System.Windows.Data.Binding myBinding = new System.Windows.Data.Binding(); myBinding.ElementName = "textBox1"; myBinding.Source = label2.Target; myBinding.Path = new PropertyPath("IsEnabled"); label2.SetBinding(TextBox.IsEnabledProperty, myBinding);
16_
How to raise an event that would be checked by compiler
C# RaisePropertyChanged(() => this.MyProperty); ... protected void RaisePropertyChanged<TProperty>(Expression<Func<TProperty>> propertyExpression) { var propertyName = ExpressionMiner.ExtractPropertyName(propertyExpression); var handler = this.PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } }
17_
Create Data trigger to change color of the TextBox when Height value gets set to 200
Model
C# <DataTemplate DataType="{x:Type loc:Person}"> <Grid> <TextBox Text="{Binding PName}" Name="textBox1" ... /> <TextBox Text="{Binding PHeight}" Name="textBox2" ... /> </Grid> <DataTemplate.Triggers> <!-- when the height value is 200 back--> <DataTrigger Binding="{Binding PHeight}" Value="200"> <Setter TargetName="textBox2" Property="Background" Value="Red" /> </DataTrigger> </DataTemplate.Triggers> </DataTemplate>
18_
Create Animation with data trigger when value changes
Model
C# <DataTemplate DataType="{x:Type loc:Person}"> <Grid> <TextBox Text="{Binding PName}" Name="textBox1" ... /> <TextBox Text="{Binding PHeight}" Name="textBox2" ... /> </Grid> <DataTemplate.Triggers> <!-- when the height value is 200 --> <DataTrigger Binding="{Binding PHeight}" Value="200"> <!-- then textbox turns to Red --> <DataTrigger.EnterActions> <BeginStoryboard> <Storyboard> <ColorAnimation Storyboard.TargetName="textBox2" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" To="Red" Duration="0:0:2" /> </Storyboard> </BeginStoryboard> </DataTrigger.EnterActions> <!-- when changed from 200 to something else then then textbox turns to Green --> <DataTrigger.ExitActions> <BeginStoryboard> <Storyboard> <ColorAnimation Storyboard.TargetName="textBox2" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" To="White" Duration="0:0:2" /> </Storyboard> </BeginStoryboard> </DataTrigger.ExitActions> </DataTrigger> </DataTemplate.Triggers> </DataTemplate>
19_
How to convert boolean to visibility
XAML <UserControl.Resources> <BooleanToVisibilityConverter x:Key="BooleanToVisibility" /> </UserControl.Resources>Then is could be used to be bound to PrintInProgress property of bool type.
XAML <Button Content="Cancel" Visibility="{Binding PrintInProgress, Converter={StaticResource BooleanToVisibility}}" Click="..." />
20_
Implement custom convertor BooleanToVisibilityWithInversionConvertor
C# public class BooleanToVisibilityWithInversionConvertor : IValueConverter { public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture) { if (targetType == typeof(Visibility)) { bool visible = System.Convert.ToBoolean(value, culture); if (parameter.ToString() == "Not") { visible = !visible; } if (InverseVisibility) { visible = !visible; } return visible ? Visibility.Visible : Visibility.Collapsed; } throw new InvalidOperationException("BooleanToVisibility2StatesConvertor can only convert to value of type Visibility."); } public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture) { throw new InvalidOperationException("BooleanToVisibility2StatesConvertor cannot convert back."); } public Boolean InverseVisibility { get; set; } }
21_
How to parametrize BooleanToVisibilityWithInversionConvertor (2 ways)
There are 2 ways. 1 using Property like "InverseVisibility" in this example.
XAML <UserControl.Resources> <myConvertors:BooleanToVisibilityWithInversionConvertor x:Key="BooleanToVisibilityWithInversion" InverseVisibility="True" /> </UserControl.Resources> ... <Grid Visibility="{Binding IsBusy, Converter={StaticResource BooleanToVisibilityWithInversion}}" />or using ConvertorParameter like in the example below.
XAML <UserControl.Resources> <myConvertors:BooleanToVisibilityWithInversionConvertor x:Key="BooleanToVisibilityWithInversion" /> </UserControl.Resources> ... <Grid Visibility="{Binding IsBusy, Converter={StaticResource BooleanToVisibilityWithInversion}, ConverterParameter='Not'}" />
22_
Create IsRed CLR Property for MyStackPanel
C# public class MyStackPanel : StackPanel { private bool _isRed; public bool IsRed { get { return _isRed; } set { _isRed = value; if (_isRed) this.Background = Brushes.Red; else this.Background = Brushes.White; } } }Then we can use it as follow in XAML
XAML <local:MyStackPanel IsRed="True" > <TextBlock>Text 1</TextBlock> </local:MyStackPanel>
23_
Create IsPurple Dependency Property for MyStackPanel
C# public class MyStackPanel : StackPanel StackPanel inherits from DependencyObject { //register the property - the name must follow the pattern: CLR Property Name + "Property" public static DependencyProperty IsPurpleProperty = DependencyProperty.Register("IsPurple", typeof(bool), typeof(MyStackPanel), // ownerType new FrameworkPropertyMetadata(false, OnIsPurpleChanged)); // create on change handler private static void OnIsPurpleChanged(DependencyObject source, DependencyPropertyChangedEventArgs ev) { bool b = (bool)ev.NewValue; MyStackPanel myStackPanel = source as MyStackPanel; if (b) myStackPanel.Background = Brushes.Purple; else myStackPanel.Background = Brushes.White; } //create CLR property public bool IsPurple { get { return (bool) GetValue(IsPurpleProperty); } set { SetValue(IsPurpleProperty, value); } } }the we can use the CLR property name for binding in XAML
XAML <local:MyStackPanel IsPurple="True" > <TextBlock>Text 1</TextBlock> </local:MyStackPanel>
24_
What is not allowed in dependency properties
XAML <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="50"/> <RowDefinition Height="50"/> <RowDefinition Height="50"/> <RowDefinition Height="50"/> </Grid.RowDefinitions> <local:MyStackPanel IsRed="False" IsPurple="False" Grid.ColumnSpan="3"> <TextBlock>isRed=false, isPurple=false</TextBlock> </local:MyStackPanel> <local:MyStackPanel Grid.Row="1" IsRed="True" IsPurple="False" Grid.ColumnSpan="3"> <TextBlock>isRed=true, isPurple=false</TextBlock> </local:MyStackPanel> <local:MyStackPanel Grid.Row="2" IsRed="False" IsPurple="True" Grid.ColumnSpan="3"> <TextBlock>isRed=false, isPurple=true</TextBlock> </local:MyStackPanel> <!-- ifyou try to set binding like this: IsRed="{Binding IsRedProp}" you will get runtime error: 'Binding' cannot be set on the 'IsRed' property of type 'MyStackPanel'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject. --> <local:MyStackPanel Grid.Row="3" IsPurple="false" Grid.ColumnSpan="3"> <TextBlock>IsRed="{Binding IsRedProp}" <-- is not allowed, isPurple=false</TextBlock> </local:MyStackPanel> <local:MyStackPanel Grid.Row="4" IsRed="False" IsPurple="{Binding IsPurpleProp}" Grid.ColumnSpan="3"> <TextBlock>isRed=false, isPurple="{Binding IsPurpleProp}"</TextBlock> </local:MyStackPanel> </Grid>
C# using System.ComponentModel; namespace Fundamentals.DependencyProperties { public class DPViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged = delegate { }; private bool _isRed; public bool IsRedProp { get { return _isRed; } set { _isRed = value; PropertyChanged(this, new PropertyChangedEventArgs("IsRedProp")); } } private bool _isPurple = true; public bool IsPurpleProp { get { return _isPurple; } set { _isPurple = value; PropertyChanged(this, new PropertyChangedEventArgs("IsPurpleProp")); } } } }
25_
How to inherit window from a base class
1. Create base Window class
3. Update NewWindow.xaml
Visual Studio create NewWindow as a class inherited from Window
C# namespace BaseClasses { public class WindowBase : Window { public WindowBase() {...} public DoSomething() {...} } }2. Create new Window
3. Update NewWindow.xaml
XAML <base:WindowBase .... x:Class="NewWindow" xmlns:base="clr-namespace:BaseClasses"4. Update NewWindow.xaml.cs
Visual Studio create NewWindow as a class inherited from Window
C# public partial class NewWindow : Window { }In order to be able to write
C# BaseWindow newWindow = new NewWindow(); newWindow.DoSomething();it is necessary to remove inheritence from Window and create the class as
C# public partial class NewWindow { }
26_
Difference between static and dynamic resources
StaticResource
- will be resolved on object construction.
- Use them if they do not change during the lifetime of the application
DynamicResource
- will be evaluated and resolved every time control needs the resource.
27_
Command in WinForm like approach
Similarly as in WinForm world it possible to assign Click property, either in XAML
XAML <Button Name="btnLikeWinForm" Click="clickCommand_Executed" Content="Click on me" />or in code
C# btnLikeWinForm.Click += clickCommand_Executed;and refer to even handler method
C# void clickCommand_Executed(object sender, EventArgs e) { // do something }When a different event handler is assigned in code and in XAML, the one in code wins.
28_
Routed command with Paste action
Routed commands can be associated with any control, not just buttons
XAML <Button Command="ApplicationCommands.Paste" Content="Press Ctrl+V when button is selected"> <Button.CommandBindings> <CommandBinding Command="ApplicationCommands.Paste" Executed="pasteCommand_Executed" /> </Button.CommandBindings> </Button>Event handler in code
XAML void pasteCommand_Executed(object sender, ExecutedRoutedEventArgs e) { // do something }
29_
How to create a custom command
If you want to create a button that will get disabled after user clicks it and enabled afetr the operation being exeuted has finished,
you can achiev it with a custom RoutedCommand bound to the button.
Define the command in your window, user control o isolated view model.
Define the command in your window, user control o isolated view model.
C# public partial class MyControl : UserControl { public static RoutedCommand MyCommand = new RoutedCommand(); private void MyButton_Click(object sender, RoutedEventArgs e) { // execute your operation } private void CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; // implement your logic to decide if the command with associated button are enabled } }In your .xaml file
XAML <Button Content="Click on me" Command="{x:Static local:MyControl.MyCommand}"> <Button.CommandBindings> <CommandBinding Command="{x:Static tabs:MyControl.MyCommand}" Executed="MyButton_Click" CanExecute="CanExecute"/> </Button.CommandBindings> </Button>Based on you decision logic implementation you may need to refresh the UI to reflect changes in model
C# // This may be needed to enable/disable the button associated with the command CommandManager.InvalidateRequerySuggested();
30_
How to use DelegetaCommand from Prism
Install Prism.Wpf Nuget package
It will add references to Prism.dll and Prism.Wpf.dll
It will add references to Prism.dll and Prism.Wpf.dll
C# public partial class MyControl : UserControl { public DelegateCommand MyCommand { get; private set; } internal MyControl() { ... MyCommand = new DelegateCommand(StartExecution, CanExecuteCommand); CanExecute = true; } private bool _canExecute; public bool CanExecute { get { return _canExecute; } set { if (value != _canExecute) { _canExecute = value; PropertyChanged(this, new PropertyChangedEventArgs("CanExecute")); MyCommand.RaiseCanExecuteChanged(); } } } public async void StartExecution() { CanExecute = false; // execute an action CanExecute = true; } private bool CanExecuteCommand() { return _canExecute; } ... }
XAML <Button Content="Click on me" Command="{Binding MyCommand}" />
31_
Grid with height of row definition
It is possible to define the height of rows or width of colums either statically with a fixed number
or dynamically so that the value gets calculted at runtime.
Auto - size will be set to accomodate content of the cell
* - will be set as max of remaining space after all Auto rows/columns were calculated
If multiple rows or columns have * specified, their size will be equal. If a row is marked with 2* it means, that its size will twice greater as rows marked with single *
More about Auto vs. *
Sizes can be constrained with Max/Min Height and Width.
Auto - size will be set to accomodate content of the cell
* - will be set as max of remaining space after all Auto rows/columns were calculated
If multiple rows or columns have * specified, their size will be equal. If a row is marked with 2* it means, that its size will twice greater as rows marked with single *
More about Auto vs. *
Sizes can be constrained with Max/Min Height and Width.
XML <Grid> <Grid.RowDefinitions> <RowDefinition Height="150" MinHeight="100"/> <RowDefinition Height="Auto" /> <RowDefinition Height="*" MaxHeight="500"/> </Grid.RowDefinitions> <Button Content="First" /> <Button Content="Second" Grid.Row="1" /> <Button Content="Third" Grid.Row="2" /> </Grid>
32_
Grid with GridSplitters
GridSplitter allows changing width of columns or rows in the Grid by mouse.
XAML <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="150" MinWidth="100"/> <ColumnDefinition Width="5" /> <ColumnDefinition Width="Auto" MinWidth="100"/> <ColumnDefinition Width="5"/> <ColumnDefinition Width="*" MinWidth="100"/> </Grid.ColumnDefinitions> <Button Content="Left" Grid.Column="0" HorizontalAlignment="Stretch" /> <GridSplitter Grid.Column="1" Width="5" Background="Yellow" HorizontalAlignment="Center"/> <Button Content="Main" Grid.Column="2" /> <GridSplitter Grid.Column="3" Width="5" Background="Yellow" HorizontalAlignment="Center"/> <Button Content="Right" Grid.Column="4" /> </Grid>When HorizontalAlignment for Splitter is set to "Center" then when the splitter is being moved, the column size, of the column where the splitter resides, will get wider, which means that the column width of the column on the left side from the splitter will remained unchanged.
33_
Diffrences between TexBlock and Label
Label inherits from ContentControl so it can be represented not only just by text.
Label can be associated with a TextBox and provides hot Key (_) that works when user presses ALT a causes to set focus on the associated TextBox.
When IsEnabled property for Labal gets set, the Label look will be grayed out, the TextBox look remains.
Label has default Padding that is similar to TextBox.
Label can be associated with a TextBox and provides hot Key (_) that works when user presses ALT a causes to set focus on the associated TextBox.
When IsEnabled property for Labal gets set, the Label look will be grayed out, the TextBox look remains.
Label has default Padding that is similar to TextBox.
XAML <Label Content="_My TextBox" Target="{Binding ElementName=textBox1}" IsEnabled="False"/> <TextBox Name="textBox1" Text="Hello"/>As Label can be disabled, it IsEnabled property can be bound to associated TextBox
XAML IsEnabled="{Binding ElementName=textBox1, Path=IsEnabled, Mode=OneWay}
34_
Bind ComboBox to enum
Having a enum definiton
C# public enum Color { Red, Blue, Green }the viewmodel needs to expose the selected value and list of all options
C# private Color _selectedColor; public Color SelectedColor { get { return _selectedColor; } set { if (value != _selectedColor) { _selectedColor = value; this.PropertyChanged(this, new PropertyChangedEventArgs("SelectedColor")); } } } public IEnumerable<Color> AllColors { get { return Enum.GetValues(typeof(Color)).Cast<Color>(); } }XML markup looks like this
XML <ComboBox ItemsSource="{Binding AllColors}" SelectedItem="{Binding SelectedColor}" />
35_
How to ensure that a button can get properly disabled/enabled
Button control in WPF has property IsEnabled. If you set the property to false
In order the button behaves like a properly disabled buttton, you need to implement a command, bind the command to the button and set CanExecute() on the commnand to false (see commands).
If you set CanExecute to false, it will cause the button to be disabled, but when you set it back to true it will not cause the button to be enabled. The button will get enabled after you change a focus manually (e.g. click Tab). This can be achieved in automated manner by calling
C# myButton.IsEnabled = false;it will not cause the button to appear disabled and user still can click the button.
In order the button behaves like a properly disabled buttton, you need to implement a command, bind the command to the button and set CanExecute() on the commnand to false (see commands).
If you set CanExecute to false, it will cause the button to be disabled, but when you set it back to true it will not cause the button to be enabled. The button will get enabled after you change a focus manually (e.g. click Tab). This can be achieved in automated manner by calling
C# CommandManager.InvalidateRequerySuggested();
36_
Scrollable TextBox for large text
XAML <ScrollViewer MaxHeight="150"> <TextBox Text="Very long text..." /> </ScrollViewer>Without MaxHeight the TextBox, when used in a Grid, will adjust its height to accomodate the text, but the row height in a Grid can make it just partly visible.
37_
How to embed an user control
XML xmlns:myControlAlias="clr-namespace:myControlNamespace;assembly=myAssemblyNameWithoutDll" ... <Grid> <myControlAlias:MyControl /> </Grid>assembly part is needed only if the user control is located in another assembly
38_
How to name and access objects (e.g.in Window)
XAML <Button Content="First" Name="buttonFirst" />Then you can obtain reference to them.
C# Button button1 = this.buttonFirst; object button2 = this.FindName("buttonFirst");
39_
What are the possible states of Visibility
Visible: Display the element. Hidden: Do not display the element, but reserve space for the element in layout. Collapsed: Do not display the element, and do not reserve space for it in layout.
40_
What is the differece between Width and ActualWidth
Width is the requested width, ActualWidth is actual withd of the control at give moment.
Width can be set to "Auto". Then is appears in debugger as "NaN".
41_
How to implement like Anchor behavior
The same behavior as Anchors in WinForms can be in WPF world achieved by setting Margins.
The same time, width and height need to be set to "auto" and Vertical and horizontal aligments
to "stretch" or those must not appear in XAML for given control.
XAML Margin="0,40,0,20" Width="auto" Height="auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
42_
How to implement WinForms equivalent of DoEvents()
XAML [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public void DoEvents() { DispatcherFrame frame = new DispatcherFrame(); Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame); Dispatcher.PushFrame(frame); } public object ExitFrame(object f) { ((DispatcherFrame)f).Continue = false; return null; }
43_
How to set focus (2 options)
It if is necessary to set only once, it can be done statically either in XAML
XAML <Window FocusManager.FocusedElement="{Binding ElementName=MyTextBox}"> <TextBox Name="MyTextBox" Text="{Binding Message}"/> </Window>or in code behind
C# MyTextBox.Focus();
44_
How to use DelegateCommand
Telerik offers own another approch that does not require commandBinding
C# Telerik.Windows.Controls.DelegateCommand : System.Windows.Input.ICommandthe event handler can be assigned directly as delegate
C# public DelegateCommand MyCommand { get; private set; } MyCommand = new DelegateCommand((o1) => {...}, (o2) => { return true; } );it can be assigned directly in code
C# myButton.Command = MyCommand;or in XAML
XAML <telerik:RadButton Name="myButton" Content="Click on me" Command="{Binding MyCommand}">Wenn command validation codition changes, it is necessary to call
C# MyCommand.InvalidateCanExecute();in order to re-evaluate the state. Wenn the command gets executed, CanExecute delegate gets evaluated again.