http://www.abhisheksur.com/2011/07/internals-of-dependency-property-in-wpf.html
A MUST read for WPF and Silverlight developers before they actually write code for clients.
Abt me :Now a mad rider on the WPF road
A MUST read for WPF and Silverlight developers before they actually write code for clients.
Another issue you are going to face is the namespace and assembly differences of classes in WPF and Silverlight.Especially you will find when dealing with controls.ie the classes will be there with same methods and properties.But in different namespaces or assemblies .That prevent us from having common code base.
Lets just consider the case of TreeView in System.Windows.Controls namespace which is present in both WPF and Silverlight.In WPF it is in the assembly PresentationFramework.dll but in Silverlight its System.Windows.Controls.dll. Ideally the schema mapping should do the correct mapping and we should be able to use the xaml. But unfortunately it is not mapped to the schema.Means if we use common xaml file for tree view it will show a compilation error in Silverlight.
The tag 'TreeView' does not exist in XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'.Does this indicate we should stop common code? Not at all.We have one solution which uses inheritance as a hack.I didn’t even think, inheritance will have such a usage.Solution is as follows.
Public Class CCBTreeView
Inherits System.Windows.Controls.TreeView
End Class
<UserControl x:Class="TestCompatibility.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CCBControls="clr-namespace:CCB.Controls;assembly=CCB.Controls">
<CCBControls:CCBTreeView ItemsSource="{Binding Persons}" />
</UserControl>
This applies to so many controls such as HierarchicalDataTemplate,TabControl etc which differs in namespace or assembly.Refer the sample uploaded here if you still have confusion.Also let me know if anybody have better solution to this problem.
Previous posts on Common Code Base
----------------------------------------------
Common Code Base 1 Introduction
Common Code Base 2 Styles and Templates
There will be some scenarios where we need to get the object of ListBoxItem which is hosting one of the the bound entity.Most probably it may be the SelectedItem.
Consider this scenario there is an business class called Employee and it’s collection class is EmployeeCollection.We have binding which binds object of EmployeeCollection to a ListBox.If we access the SelectedItem property of ListBox it will return the Employee object.But the requirement is to get the ListBoxItem which hosts the selected entity on an event say SelectionChanged.
Dim lbi As ListBoxItem = lstBox.ItemContainerGenerator.ContainerFromItem(lstBox.SelectedItem)
The above code can be used to get ListBoxItem of any object which is present in the collection.
When you put a loop and try to update the ProgressBar from that loop, it will not update the visual.The visual will update only after the execution of the loop.ie you can’t see the incremental animation.Here is the solution for that issue.
Private Sub btn_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
IncrementContinuously()
End Sub
Sub IncrementContinuously()
For i = 0 To 50
Thread.Sleep(100)
prgs.Dispatcher.Invoke(New CrossAppDomainDelegate(AddressOf IncrementBy1), DispatcherPriority.Background, Nothing)
Next
End Sub
Sub IncrementBy1()
prgs.Value = prgs.Value + 1
End Sub
This link contains some more solutions.
Simple but important feature which really help us in real-time applications.Giving different look and feel or colors to alternate rows helps users to differentiate two consecutive rows in a ListBox or ListView.Basically controls which are derived from ItemsControl.
Below xaml code shows how alternate colors are applied into a ListBox
Xaml code to create ListBox with 6 items
<ListBox AlternationCount="2">
<ListBoxItem Content="Item1" />
<ListBoxItem Content="Item2" />
<ListBoxItem Content="Item3" />
<ListBoxItem Content="Item4" />
<ListBoxItem Content="Item5" />
<ListBoxItem Content="Item6" />
</ListBox>
Xaml code of the Style which has the alternate style support.Note the change is in the ItemContainerStyle.Here Style is applied to ListBoxItem
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex"
Value="0">
<Setter Property="Background"
Value="LightBlue"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex"
Value="1">
<Setter Property="Background"
Value="LightGreen"></Setter>
</Trigger>
</Style.Triggers>
</Style>
When we run it shows as follows
Description
Here the ItemsControl has got most of the implementation part.It has some members which control the behavior of alternate style.The attached property ItemsControl.AlternationIndex tells the index and according to that we can change color or anything through style.
The Alternation count specifies the frequency.Below code uses 3 as ItemsControl.AlternationCount.See the difference.
Creating ListBox
<ListBox AlternationCount="3">
<ListBoxItem Content="Item1" />
<ListBoxItem Content="Item2" />
<ListBoxItem Content="Item3" />
<ListBoxItem Content="Item4" />
<ListBoxItem Content="Item5" />
<ListBoxItem Content="Item6" />
</ListBox>
Style supports AlternationCount=3
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex"
Value="0">
<Setter Property="Background"
Value="LightBlue"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex"
Value="1">
<Setter Property="Background"
Value="LightGreen"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex"
Value="2">
<Setter Property="Background"
Value="LightYellow"></Setter>
</Trigger>
</Style.Triggers>
</Style>
I don't think a sample is needed.
The first Service pack for Microsoft surface has released on May 10.It has got significant changes comparing to the older older.Here are the main features I noticed.
More details here
http://blogs.msdn.com/surface/archive/2009/05/11/service-pack-1-officially-released-today.aspx
http://arstechnica.com/microsoft/news/2009/05/microsoft-surface-sp1-adds-new-features.ars
As a developer, I am more interested in the new controls and will be posting about them later.
I am very happy to see that my previous post “WPF Watermark TextBox using XAML Style” helped a lot of peoples to solve their issues and currently that is the most popular post in my blog.That post describes about creating a WPF watermark textbox by changing it’s style.All the things are done in xaml and there is no property to set the water mark text.
There was a requirement from one of the readers for such a property.ie a Watermark property which decides the watermark text.So rewriting the sample with that property.
Here I just derived a new class called WatemarkTextBox from standard TextBox added a new dependency property called Watermark and defined default style for that control in generic.xaml.The steps are as follows
public class WatermarkTextBox : TextBox
{
static WatermarkTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkTextBox),
new FrameworkPropertyMetadata(typeof(WatermarkTextBox)));
}
public object Watermark
{
get { return (object)GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
}
// Using a DependencyProperty as the backing store for Watermark. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
"Watermark",
typeof(object),
typeof(WatermarkTextBox),
new UIPropertyMetadata(null));
}
<Style TargetType="{x:Type local:WatermarkTextBox}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderBrush"
Value="Blue" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Padding"
Value="1" />
<Setter Property="AllowDrop"
Value="true" />
<Setter Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:WatermarkTextBox}">
<Grid>
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd"
SnapsToDevicePixels="true"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
RenderFocused="{TemplateBinding IsKeyboardFocusWithin}"
RenderMouseOver="{TemplateBinding IsMouseOver}">
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Microsoft_Windows_Themes:ListBoxChrome>
<TextBlock x:Name="textBlock"
Opacity="0.345"
Text="{TemplateBinding Watermark}"
TextWrapping="Wrap"
Visibility="Hidden" />
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused"
Value="False" />
<Condition Property="Text"
Value="" />
</MultiTrigger.Conditions>
<Setter Property="Visibility"
TargetName="textBlock"
Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Download sample from here.
Name | Description |
TextBox.Select() | Accepts initial position and length of selection. |
TextBox.SelectAll() | Selects full text. |
TextBox.SelectionStart | Direct property which tells the start of selection. |
TextBox.SelectionLength | Direct property which tells the length of selection. |
TextBox.SelectedText | Gives the currently selected text. |
But if you just use these methods and properties the selection will not come as expected.ie the text won't get selected even if we set these properties or call methods.
The reason for this is very simple.The TextBox is not in focus.So make sure that the TextBox is in focus before using programmatic selection related members.Or give Focus to the TextBox before selecting.
tbResult.Focus();
tbResult.SelectionStart = tbResult.Text.IndexOf("ControlTemplate TargetType=");
tbResult.SelectionLength = 230;
What is watermarked TextBox
Watermarked TextBox is a special type of text input control which displays a message or image when it is empty.Usually the message will be "Enter the text" and sometimes it may be description about that data field.
When we click on the TextBox ie getting focus the watermark text ("Enter the text") will disappear and it will become an ordinary TextBox.
Developing Watermark TextBox
The tasks of developer are hiding the watermark on getting focus and showing again on lost focus, if the user doesn't entered value in that.ie if the TextBox is empty watermark should come again.
In earlier days this itself was a control which is inherited from normal TextBox.But with the help of Templating and Trigger support in WPF we could achieve it very easily without inheriting.Just by Stying and Templating an ordinary TextBox.
Structure of Watermark TextBox Style
The style can be based on the style of TextBox itself.This reduces our effort in implementing normal TextBox behaviors.We are just going to concentrate on Template.
The normal TextBox template contains a ScrollViewer to hold the data.We are just going to put a TextBlock over that which is going to hold the Watermark text("Enter the Text").By default the visibility of this new TextBlock will be hidden.
Inside ControlTemplate
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<TextBlock x:Name="textBlock"
Opacity="0.345"
Text="Enter Text Here"
TextWrapping="Wrap"
Visibility="Hidden" />
</Grid>
Now we write Trigger to show this TextBlock on demand.There are two conditions which shows this watermark.They are "IsFocused=False" and Length of the Text=0.So we write a MultiTrigger with 2 conditions in it.One is for LostFocus and other is for Text.Length respectively.
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused"
Value="False" />
<Condition Property="Text"
Value="" />
</MultiTrigger.Conditions>
<Setter Property="Visibility"
TargetName="textBlock"
Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
Now whenever the TextBox comes in a state where the IsFocused=False and Text="" the Watermark TextBlock will get displayed.You can replace the watermark TextBlock by any image or what ever you want..
Complete Style
<Style x:Key="WaterMarkTextBoxStyle"
BasedOn="{StaticResource {x:Type TextBox}}"
TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<TextBlock x:Name="textBlock"
Opacity="0.345"
Text="Enter Text Here"
TextWrapping="Wrap"
Visibility="Hidden" />
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused"
Value="False" />
<Condition Property="Text"
Value="" />
</MultiTrigger.Conditions>
<Setter Property="Visibility"
TargetName="textBlock"
Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This can be done by a graphics designer alone.That means using Expression Blend.Will be posting steps later.
Here attached a sample which demonstrates this.
MyUserControl holds a slider and we are going to expose the Value DP of this through MyUserControl.
So add Value DP to MyUserControl and Bind that to Value DP of inner slider.
public partial class MySlider : System.Windows.Controls.UserControl
{
public MySlider()
{
InitializeComponent();
}
public static readonly DependencyProperty ValueProperty=DependencyProperty.Register("Value",typeof(double),typeof(MySlider));
public double Value
{
get
{
return (double)GetValue(MySlider.ValueProperty);
}
set
{
SetValue(MySlider.ValueProperty, value);
}
}
}