= WPF Basic Controls =
== Border ==
''Border'' control with rounder corners:
''Border'' control using ''Style'' to apply rounded corners:
''Border'' with header region:
''Border'' with some style:
Data Here...
''Border'' with ''DropShadowEffect'':
== Button or ToggleButton ==
Standard button:
Toggle button:
Button with gradient background:
Button with gradient background style:
...
A ''Button'' with shadow bitmap effect:
A button style:
Possible bitmap effects:
* ''DropShadowEffect''
* ''BlurEffect''
* [[http://msdn.microsoft.com/en-us/library/ms752092.aspx|Bitmap Effects How-to Topics]]
* [[http://www.designerwpf.com/2008/02/08/wpf-drop-shadows-on-the-cheap|WPF Drop Shadows on the Cheap]]
Reflection effect:
For programmatically clicking on a button:
myButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
Tooltips on a button:
More Creative:
* [[swdev:dotnet:Drop Down Button]]
== Cursor ==
Changing cursors programmatically (eg: pen, cross, scroll, etc.):
this.Cursor = Cursors.None;
Using custom cursors:
this.Cursor = new Cursor("CustomCursorImage.jpg");
Using custom cursors via XAML:
== DataGrid ==
Types of columns
* DataGridTextColumn: For string values.
* DataGridCheckBoxColumn: For boolean values.
* DataGridComboBoxColumn: For enumerated types, or lists.
* DataGridHyperlinkColumn: For URI values.
* DataGridTemplateColumn: For custom fields.
Attributes:
* CanUserAddRows: Activates additional empty row at the bottom.
* IsReadOnly: Set grid to read only.
* FrozenColumnCount: Set the number of columns to freeze on the left side.
* IsSynchronizedWithCurrentItem: Set synchronization with DataContext or other data binding method, so that other controls using that data bind will be synchronized as well.
* AlternatingRowBackground: Sets color for alternating background.
* AlternationCount: Set number of rows before alternating colors.
XAML:
Product Specifications Matrix
To add a row programmatically: DataGrid.Items.Add(new DataItem());
To add a column programmatically: DataGrid.Columns.Add(new DataGridTextColumn());
To add data to ''DataGrid'' programmatically:
...
// assuming x:Name="myGrid" in markup
// add rows to grid (same logic for columns as well)
for (int row=0; row < numRows; row++)
{
myGrid = RowDefinitions.Add(new RowDefinition());
}
// Stick a control in intended location
b = new Button();
myGrid.Children.Add(b);
Grid.SetRow(b,1); // 2nd row
Grid.SetColumn(b,3); // 4th column
Grid.SetColumnSpan(b,2);
b.Style = (Style)FindResource("myButtonStyle"); // defined in MyApp.xaml
...
* [[http://www.switchonthecode.com/tutorials/using-the-wpf-toolkit-datagrid|Using the WPF Toolkit DataGrid]]
* [[http://www.dotnetspark.com/kb/1943-add-tooltip-datagrid-wpf.aspx|Add Tooltip Datagrid WPF]]
* [[http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx|WPF Datagrid Examples]]
* [[http://blogs.msdn.com/b/vinsibal/archive/2008/08/19/wpf-datagrid-stock-and-template-columns.aspx|WPF Datagrid Stock and Template Columns]]
* [[http://msdn.microsoft.com/en-us/library/ff407126.aspx|MSDN: How to: Group, Sort, and Filter Data in the DataGrid Control]]
* [[http://blogs.msdn.com/b/jaimer/archive/2009/01/20/styling-microsoft-s-wpf-datagrid.aspx|Styling Microsoft's WPF DataGrid]]
== Expander ==
Expander with a ListBox inside:
Modify Expander header style:
Patients
Expander with Popup content:
Resources:
* [[http://karlshifflett.wordpress.com/2008/02/05/wpf-sample-series-expander-control-with-popup-content/|WPF Expander control with popup content]].
== FlowDocument ==
Example of ''FlowDocument'' contained in ''FlowDocumentReader'' control:
Main ReportPatient DetailsName: John DoeAddress: 1250 Main Street, Orange, FL 32700Tested Binaurally
LeftRightBothXXXYYY
New Page HereGoogle Search
More in depth:
* [[http://msdn.microsoft.com/en-us/library/aa970909.aspx|MSDN: Flow Document Overview]]
* [[http://msdn.microsoft.com/en-us/library/ms747133.aspx|MSDN: Flow Document Table Overview]]
* [[http://msdn.microsoft.com/en-us/library/system.windows.documents.table.aspx|MSDN: Flow Document Table Class]]
* [[http://msdn.microsoft.com/en-us/library/ms522801.aspx|MSDN: Flow Document Section Class]]
A ''FlowDocument'' can also be at the layout root:
...
...
You can print it using:
// Print Document
PrintDialog dlg = new PrintDialog();
dlg.PrintDocument(((IDocumentPaginatorSource)flowdocReport).DocumentPaginator, "Main Report");
For printing FlowDocuments and data binding, see [[http://www.hanselman.com/blog/TheWeeklySourceCode40TweetSharpAndIntroducingTweetSandwich.aspx|Introducing Tweet Sandwich]]
You can load a xaml file dynamically:
void LoadFlowDocumentScrollViewerWithXAMLFile(string fileName)
{
// Open the file that contains the FlowDocument...
System.IO.FileStream xamlFile = new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
// Parse the file with the XamlReader.Load method.
FlowDocument content = System.Windows.Markup.XamlReader.Load(xamlFile) as FlowDocument;
// Alternatively:
// If the FlowDocument references external resources (such as image files) using
// relative uniform resource identifiers (URIs), it is necessary to specify a
// ParserContext that includes a BaseUri so that the parser can make sense of the
// relative URIs. The XamlReader class provides Load method that accepts a ParserContext.
//FlowDocument content = System.Windows.Markup.XamlReader.Load(xamlFile,
// new System.Windows.Markup.ParserContext() { BaseUri = new Uri("/images/icons/") } ) as FlowDocument;
// Finally, set the Document property to the FlowDocument object that was
// parsed from the input file.
flowdocReportViewer.Document = content;
xamlFile.Close();
}
Source: [[http://msdn.microsoft.com/en-us/library/ms753299.aspx|MSDN: How to: Load a XAML File into a FlowDocumentScrollViewer]]
To make use of bindable text, make sure to include this:
using System;
using System.Windows;
using System.Windows.Documents;
namespace AHI.App.Tools
{
///--------------------------------------------------------------------------------------------
///
/// A subclass of the Run element that exposes a DependencyProperty property
/// to allow data binding.
/// Source: Filipe Fortes, BindableRun, http://www.fortes.com/2007/bindablerun
///--------------------------------------------------------------------------------------------
/// Usage:
///
///
///
///
/// You can control the value of this text through the TextBox below:
///
///
///
///
///
///
///
///
///
///
///--------------------------------------------------------------------------------------------
public class TBindableRun : Run
{
public static readonly DependencyProperty BoundTextProperty = DependencyProperty.Register(
"BoundText",
typeof(string),
typeof(TBindableRun),
new PropertyMetadata(new PropertyChangedCallback(TBindableRun.onBoundTextChanged))
);
private static void onBoundTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Run)d).Text = (string)e.NewValue;
}
public String BoundText
{
get { return (string)GetValue(BoundTextProperty); }
set { SetValue(BoundTextProperty, value); }
}
}
}
== GeometryDrawing ==
Example of ''GeometryDrawing'' embeddeed in ''Image'' control:
Another example:
As a resource:
M0,0 L1,0 0.5,1ZM0,1 L1,1 0.5,0ZM0,0 L1,0.5 0,1ZM0,0.5 L1,1 1,0ZM0,0 L1,1 M0,1 L1,0M0,0 L0,1 L1,1 L1,0Z
== Grid and GridSplitter ==
=== Populating a Grid programmatically ===
C#:
private void btnAddPanel1_Click()
{
// How to add a child grid to col 0, row 1, colspan=3
Grid grdPanel1 = new Grid();
grdRoot.Children.Add(grdPanel1);
Grid.SetRow(grdPanel1, 1);
Grid.SetColumn(grdPanel1, 0);
Grid.SetColumnSpan(grdPanel1, 3);
// How to add new row definition
grdRoot = RowDefinitions.Add(new RowDefinition());
}
Assumming:
== InkCanvas ==
Setup a space that you can paint at run time:
== Image ==
Programmatically (assuming image "Build Action" is set to "Content"):
Image imgProduct = new Image();
//Uri src = new Uri(@"/MyComponentName;component/images/icons/icon-product.png", UriKind.Relative);
Uri src = new Uri("/images/icons/icon-product.png", UriKind.RelativeOrAbsolute);
BitmapImage img = new BitmapImage(src);
imgProduct.Source = img;
Programmatically (assuming image "Build Action" is set to "Resource"):
static internal ImageSource GetImageSourceFromResource(string psAssemblyName, string psResourceName)
{
Uri oUri = new Uri("pack://application:,,,/" + psAssemblyName + ";component/" + psResourceName, UriKind.RelativeOrAbsolute);
return BitmapFrame.Create(oUri);
}
...
Image imgProduct = new Image();
imgProduct.Source = GetImageSourceFromResource("MyComponentName", @"images/icons/icon-product.png");
When reusing an image, to save memory, create a ''BitmapSource'' as a resource:
Then use it:
Set the ''img.png'' file's "Build Action" to "Resource" instead of "Content" to embed it with the executable.
Using the Clipboard:
// Copy to Clipboard
System.Drawing.Image imgSrc; //... image files with content at some point
...
System.IO.MemoryStream fs = new System.IO.MemoryStream();
imgSrc.SaveImage(fs, System.Drawing.Imaging.ImageFormat.Png);
System.Drawing.Image imgToCopy = System.Drawing.Image.FromStream(fs);
System.Windows.Forms.Clipboard.SetImage(imgToCopy);
// Copy from Clipboard
imgTarget.Source = Clipboard.GetImage();
== ListBox ==
Normal List:
Horizontal List:
Horizontal List with WrapPanel:
References:
* [[http://vbcity.com/blogs/xtab/archive/2009/06/28/background-color-for-wpf-listbox-selected-item.aspx|Changing background color for selected item in WPF ListBox]]
== ListView ==
References:
* [[http://msdn.microsoft.com/en-us/library/ms611074.aspx|ListView Class]]
== MediaElement ==
To play video (or audio) clips, you can use the ''MediaElement'' control.
WPF control:
C# code behind:
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
player.LoadedBehavior = MediaState.Manual;
player.Source = new Uri(@"media\softtouch.wmv", UriKind.Relative);
player.Play();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
player.Stop();
}
== Popup ==
A button that will open a Popup window when clicked:
This is popup text
=== Popup Position Tracking ===
. . .
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
...
namespace ezFIT
{
///
/// Interaction logic for ucMain.xaml
///
public partial class ucMain : UserControl
{
. . .
///----------------------------------------------------------------------------------------
///
/// Loaded event handler for user control.
///
///
///
///----------------------------------------------------------------------------------------
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// Subscribe to SizeChanged and LocationChanged events from parent window,
// in order to update popup menus correctly.
Window ParentWin = MyLib.App.Tools.TSystemUtils.FindAnchestor((DependencyObject)e.OriginalSource);
ParentWin.SizeChanged += new SizeChangedEventHandler(ParentWin_SizeChanged);
ParentWin.LocationChanged += new EventHandler(ParentWin_LocationChanged);
}
///----------------------------------------------------------------------------------------
///
/// LocationChanged event handler used for event subscription by parent window.
///
///
///
///----------------------------------------------------------------------------------------
void ParentWin_LocationChanged(object sender, EventArgs e)
{
ResetPopUp(popmnuHelp);
}
///----------------------------------------------------------------------------------------
///
/// SizeChanged event handler used for event subscription by parent window.
///
///
///
///----------------------------------------------------------------------------------------
void ParentWin_SizeChanged(object sender, SizeChangedEventArgs e)
{
ResetPopUp(popmnuHelp);
}
///----------------------------------------------------------------------------------------
///
/// Reset the specified Popup.
///
/// Popup to reset
///----------------------------------------------------------------------------------------
public void ResetPopUp(Popup aPopup)
{
Random random = new Random();
aPopup.PlacementRectangle = new Rect(
new Point(random.NextDouble() / 1000 /* x coord */, 0 /* y coord */),
new Size(100 /* width */, 25 /* height */)
);
}
. . .
}
}
Useful links:
* [[http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/27950e73-0007-4e0b-9f00-568d2db1d979|Popup tracking position of PlacementTarget.]]
* [[http://stackoverflow.com/questions/5948378/how-to-detect-that-a-control-is-being-moved|How to detect that a control is being moved?]]
== Path ==
To create a geometric figure using ''Path'':
M 0 4 L 4 0 L 8 4 ZM 0 0 L 4 4 L 8 0 Z
...
Or paint directly to a ''Canvas'':
== Polygon ==
Creating polygons with behavior. In this example, some triangles working as thumbnails:
Supporting C# code:
private void thumbBinauralUp_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
// Do work here
MessageBox.Show("Binaural Up");
}
private void thumbLeftUp_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
// Do work here
MessageBox.Show("Left Up");
}
== ProgressBar==
''ProgressBar'' example using dynamic resources:
== RadioButton ==
To group several ''RadioButton''s, make them part of the same group:
To determine which ''RadioButton'' was selected in a group:
private void RadioButton_Click(object sender, RoutedEventArgs e)
{
if( btnMem1.IsChecked == true)
{
MessageBox.Show(btnMem1.Content.ToString());
}
else if (btnMem2.IsChecked == true)
{
MessageBox.Show(btnMem2.Content.ToString());
}
else if (btnMem3.IsChecked == true)
{
MessageBox.Show(btnMem3.Content.ToString());
}
else
{
MessageBox.Show(btnMem4.Content.ToString());
}
}
== Rectangle ==
A ''Rectangle'' geometric figure:
== Slider ==
''Slider'' example:
And some sample code to handle the slider changes:
void slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
double value = e.NewValue;
ImageBrush imageBrush = this.FindName("imageBrush") as ImageBrush;
imageBrush.Viewbox = new Rect(0.3, 0.3, 1 / value, 1 / value);
}
References:
* [[http://nayyeri.net/slider-control-in-windows-presentation-foundation|Slider Control in WPF]]
* [[http://codingsense.wordpress.com/2010/02/01/customize-a-slider-in-wpf-step-by-step-tutorial/|Customize a Slider in WPF]]
== TabControl ==
''TabControl'' with ''TabItem'' on the right side:
References
* [[http://stackoverflow.com/questions/189370/how-to-put-wpf-tab-control-tabs-on-the-side|How to put WPF tab control tabs on the side]]
== TextBlock ==
''TextBlock'' with linebreak:
Hello World!
''TextBlock'' with space and newline preservation:
Hello
World!
''TextBlock'' with truncated text showing tooltip displaying full text :
This is a long sentence with text.
Alternatively, use a behavior: [[http://tranxcoder.wordpress.com/2008/10/12/customizing-lookful-wpf-controls-take-2|Customizing "Lookful" WPF controls]]
== TextBox ==
''TextBox'' that has auto highlighted text when control gains focus:
Code to highlight:
///----------------------------------------------------------------------------------------
///
/// Highlight text in a textbox control when control gains focus.
///
///
///
///----------------------------------------------------------------------------------------
private void txtbox_GotFocus(object sender, RoutedEventArgs e)
{
//textbox.SelectionStart = 0;
//textbox.SelectionLength = textbox.Text.Length;
((TextBox)sender).SelectionStart = 0; // Start selection at beginning.
((TextBox)sender).SelectionLength = ((TextBox)sender).Text.Length; // Length of text in Text1.
}
''TextBox'' with a scrollbar:
This is a TextBox
== TreeView ==
private void treeFittingOperations_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs
== Timer ==
In WPF, ''Timer'' runs on a separate thread from the UI thread, so you need to use ''DispatcherTimer'' instead:
void ActivateTimer()
{
// using System.Windows.Threading;
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(10); // 10 seconds
timer.Tick += new EventHandler(timer_Tick); // Subscribe to Tick event handler
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
// Do something every tick
}
== URI ==
To create a ''URI'' programmatically:
// Absolute URI (default)
Uri absoluteUri = new Uri("pack://application:,,,/File.xaml", UriKind.Absolute);
// Relative URI
Uri relativeUri = new Uri("/File.xaml", UriKind.Relative);
More information: [[http://msdn.microsoft.com/en-us/library/aa970069.aspx|MSDN: Pack URIs in WPF]]
== WebBrowser ==
A simple ''WebBrowser'' control:
Clicking a button to load a web page:
private void btnWebsite_Click(object sender, RoutedEventArgs e)
{
// External Website
HtmlBrowserReport.Navigate(new Uri("http://www.example.com", UriKind.RelativeOrAbsolute));
}
private void btnViewReport_Click(object sender, RoutedEventArgs e)
{
// Local web page
// NOTE: Use siteoforigin for local files. Only files relative to application folder can be opened
// No GET parameters can be passed through URI.
// More Reading: http://www.dotnetfunda.com/articles/article840-working-with-webbrowser-in-wpf.aspx
//HtmlBrowserReport.Navigate(new Uri("pack://siteoforigin:,,,/htmlpage1.htm", UriKind.RelativeOrAbsolute));
HtmlBrowserReport.Navigate(new Uri("pack://siteoforigin:,,,/reports/report.htm", UriKind.RelativeOrAbsolute)); // located in subdir "reports"
}
Execute a JavaScript routine from C#: (see more: [[http://www.dotnetfunda.com/articles/article840-working-with-webbrowser-in-wpf.aspx|Working with WebBrowser in WPF]])
public class TSampleApp
{
// Fields
private WebBrowser aWebBrowser;
. . .
// Constructor
public TSampleApp()
{
aWebBrowser = new WebBrowser();
aWebBrowser.LoadCompleted -= new LoadCompletedEventHandler(aWebBrowser_LoadCompleted);
aWebBrowser.LoadCompleted += new LoadCompletedEventHandler(aWebBrowser_LoadCompleted);
}
public void LoadWebPage(string aWebPage)
{
// Load a webpage using Source property or Navigate() method
// Load an external website
aWebBrowser.Navigate("http://www.example.com");
aWebBrowser.Navigate(new Uri("http://www.example.com", UriKind.RelativeOrAbsolute));
// Load a local file
aWebBrowser.Navigate("Products/Catalog/prodspec.htm");
aWebBrowser.Source = new Uri(@"pack://siteoforigin:,,,/Products/Catalog/prodspec.htm", UriKind.RelativeOrAbsolute);
}
void aWebBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
// Call JavaScript routine after the document has been loaded completely
// Example:
//aWebBrowser.InvokeScript("getAlert"); // call javascript function with no params
//aWebBrowser.InvokeScript("LoadDoc", new object[] { "prod_Name.pdf" }); // call javascript function with params
string AppDir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
string ProdSpecPDFFilePath = "file:///" + System.IO.Path.Combine(AppDir, string.Format(@"Products\Catalog\{0}.pdf", _SelectedProduct.Code)).Replace("\\", "\\\\");
aWebBrowser.InvokeScript("LoadDoc", new object[] { ProdSpecPDFFilePath });
}
}
Sample HTML page with JavaScript to call:
This page comes from Stream
== Window ==
A simple ''Window'':
A ''Window'' without border, with custom Maximized, Minimized, Closed, Drag, and Stretch functionality:
///
/// Interaction logic for winMain.xaml
///
public partial class winMain : Window
{
public winMain()
{
InitializeComponent();
}
private void frmMain_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Drag Window (especially if no border is present)
this.DragMove();
}
private void btnWinMin_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
private void btnWinMax_Click(object sender, RoutedEventArgs e)
{
if (this.WindowState == WindowState.Normal)
{
this.WindowState = WindowState.Maximized;
this.btnWinMax.Content = "Normal";
}
else
{
this.WindowState = WindowState.Normal;
this.btnWinMax.Content = "Max";
}
}
private void btnWinClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
NOTE: Using ''AllowsTransparency="True"'' with ''WindowsFormsHost'' control will actually hide the WinForms content inside ''WindowsFormsHost''. It is a known issue. Basically, it does not paint when set to ''AllowsTransparency="True"''.
=== Dual Monitor Support ===
Source: [[http://shankarmanne.blogspot.com/2010/06/to-open-wpf-window-in-dual-monitor.html|Shankar Manne: To Open WPF window in Dual Monitor]]
Here in this example I created two windows, one is InternalWindow and other is ExternalWindow. My requirement is to open the InternalWindow in First Monitor and ExternalWindow in SecondMonitor, for that go to ''App.xaml'', remove ''StartUpUri'' and override the following method:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
InternalMain WinInternal = new InternalMain();
ExternalMain WinExternal = new ExternalMain();
Screen s1 = Screen.AllScreens[0];
Rectangle r1 = s1.WorkingArea;
WinInternal.Top = r1.Top;
WinInternal.Left = r1.Left;
if (Screen.AllScreens.Length > 1)
{
Screen s2 = Screen.AllScreens[1];
Rectangle r2 = s2.WorkingArea;
WinExternal.Top = r2.Top;
WinExternal.Left = r2.Left;
WinExternal.Show();
}
else
{
System.Windows.MessageBox.Show("External Monitor is not connected",
"Dual Monitor Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
WinInternal.Show();
WinExternal.Owner = WinInternal;
}
Note: ''WindowStartupLocation'' should not be set to ''Center''
= References =
* [[http://community.irritatedvowel.com/blogs/pete_browns_blog/archive/2009/01/09/Dazzling-Silverlight-Toolkit-Pie-Charts-with-Overlays.aspx|Toolkit Charts with Overlays]]