= Data Binding = If XAML markup is going to be used for data binding, you must use an ''ObjectDataProvider'' or ''XMLDataProvider''. If using an existing object, you can only use ''DataContext'' as your data binding. This requires the object manipulation to be done programmatically only. == Attributes == === Mode === To specify the direction and frequency of the binding. * OneTime * OneWay * TwoWay * OneWayToSource === Converter === To specify a converter to use in data conversion from the target to the source. === ConverterParameter === To specify additional parameters to the converter. Example: . . . . . . Custom type declared in Acme.App.Types.dll assembly: public enum TSide { Left Right } Custom ValueConverter declared in Acme.App.ViewModel.dll assembly (view model): ///============================================================================================ /// /// Class TInstrumentSideDetectedToVisibilityConverter /// ///============================================================================================ public class TInstrumentSideDetectedToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Visibility _visibility; if ( ((TInstrumentDetectedResults)value == TInstrumentDetectedResults.Left) && ((TSide)parameter == TSide.Left) || ((TInstrumentDetectedResults)value == TInstrumentDetectedResults.Both) && ((TSide)parameter == TSide.Left) || ((TInstrumentDetectedResults)value == TInstrumentDetectedResults.None) && ((TSide)parameter == TSide.Left) || ((TInstrumentDetectedResults)value == TInstrumentDetectedResults.Right) && ((TSide)parameter == TSide.Right) || ((TInstrumentDetectedResults)value == TInstrumentDetectedResults.Both) && ((TSide)parameter == TSide.Right) || ((TInstrumentDetectedResults)value == TInstrumentDetectedResults.None) && ((TSide)parameter == TSide.Right) ) { _visibility = Visibility.Visible; } else { _visibility = Visibility.Collapsed; } return _visibility; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } ==== UpdateSourceTrigger ==== To specify when the target property is updated. * LostFocus * PropertyChanged * Explicit === FallbackValue === To specify a default value when the binding fails. === Source, RelativeSource, ElementName === Only one of these Binding attributes should be set: * ''Source'', when referring to an object (see also [[http://msdn.microsoft.com/en-us/library/system.windows.data.binding.source.aspx|Binding.Source]]): Example: ... ... C# examples: // Examples Binding my_binding1 = new Binding(); my_binding1.Source = my_data_object; Binding my_binding2 = new Binding("PersonName"); my_binding2.Source = myDataSource; * ''RelativeSource'', when referring to current element with ''Self'', ''FindAncestor'', and ''PreviousData'' (see also [[http://msdn.microsoft.com/en-us/library/system.windows.data.binding.relativesource.aspx|Binding.RelativeSource]]): Example: Using ''RelativeSource'' to find Ancestor: C# examples: // Examples Binding my_binding1 = new Binding(); my_binding1.RelativeSource = RelativeSource.Self; Binding my_binding2 = new Binding(); my_binding2.RelativeSource = new RelativeSource(RelativeSourceMode.FinAncestor, typeof(StackPanel), 1); Binding my_binding3 = new Binding(); my_binding3.RelativeSource = RelativeSource.TemplatedParent; * ''ElementName'', when referring to a control (see also [[http://msdn.microsoft.com/en-us/library/system.windows.data.binding.elementname.aspx|Binding.ElementName]]): Example: Green Blue Red Or an example using a ''Slider'': Alternatively: C# examples: // Examples Binding my_binding1 = new Binding(); my_binding1.ElementName = "btnStart1"; Binding my_binding2 = new Binding("Value"); my_binding2.ElementName = "Slider1"; References: [[http://wpfguy.blogspot.com/2009/01/what-is-difference-source-vs.html|What is the Difference Between ''Source'' and ''RelativeSource'']] === DataContext === To bind to the default ''DataContext'' of an object (or parent), use: Programmatically in C#: ccDetails.SetBinding(ContentControl.ContentProperty, new Binding()); If you need to include the path, then use: ccDetails.SetBinding(ContentControl.ContentProperty, new Binding("Person.Name")); If the path contains an index, then use: ccDetails.SetBinding(ContentControl.ContentProperty, new Binding("Person.Address[0]")); // numeric-based index ccDetails.SetBinding(ContentControl.ContentProperty, new Binding("Person.Address[Home]")); // key-based index == Data Providers == === DataContext === Create Binding programmatically in C#: Product ProdDataSource = new Product("Bicycle"); Binding ProdBinding = new Binding("Name"); ProdBinding.Source = ProdDataSource; // txtProdName is an instance of TextBlock txtProdName.SetBinding(TextBlock.TextProperty, ProdBinding); Alternatively, for existing object instance: lstProducts.DataContext = aProdSpecsListObject; === Built-in (Primitive) Types === In XAML: 42 Oui ... * References: [[http://msdn.microsoft.com/en-us/library/ee792002.aspx|MSDN: Built-in Types for Common XAML Language Primitives]] === ObjectDataProvider === This provides binding to .NET data types. To reference data types defined in a library, add the library reference (such as ''xmlns:local="clr-namespace:Acme.Products.Specifications'') to namespace in user control's XAML, then add ''ObjectDataProvider'' resource. .... Alternatively, as an XAML element: Declaring a data source with parameters vs no parameters: Acme Define the data type in library. Eg: Acme.Products.Specification.dll using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Acme.Products.Specifications { public class TProductSpecificationList : List { public TCustomCompany CustomCompany = TCustomCompany.Acme; // Parameterless Constructor public TProductSpecificationList(): this(TCustomCompany.Acme) { } // Constructor with Parameters public TProductSpecificationList(TCustomCompany aCustomCompany) { if (CustomCompany == TCustomCompany.Acme) { this.Add("Bicycle"); this.Add("Tricyle"); } } } } Perform data binding in user control's WPF: === XmlDataProvider === This provides binding to XML data (as a resource, or external file). Create an XML data island resource for the window o user control. Bicycle 2 Red Tricycle 3 Blue .... Alternatively, put the data in an XML file. ... Call the data locally: Remotely: Perform data binding in one of these 2 ways: == Clearing Binding == To clear data binding programmatically (for a ''TextBox'' called ''txtName''): BindingOperations.ClearBinding(txtName, TextBox.TextProperty); = Examples = == Syntax == Declaring an ''ObjectDataProvider'': This notation will create an instance of that class, and you use the ''x:Key'' name to access it. == Connecting to a user defined object == ... using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Acme.Products.Specifications { public class TProductSpecification { public string Type { get; set; } public string Name { get; set; } public int Wheels{ get; set; } public string Color { get; set; } public TProductSpecification() { Type = ""; Name = ""; Wheels = 4; Color = ""; } public override string ToString() { return String.Format("{0}={1}", this.Name, this.Type); } } public class TProductSpecificationList : List { private TProductSpecification prod; public TProductSpecificationList() { prod = new TProductSpecification(); prod.Type = "prod_Bicycle"; prod.Name = "Bicycle"; prod.Wheels = 2; prod.Color = "Red"; this.Add(prod); prod = new TProductSpecification(); prod.Type = "prod_Tricycle"; prod.Name = "Tricycle"; prod.Wheels = 3; prod.Color = "Blue"; this.Add(prod); } } } == Connecting to a XAML Object == ... ABC 123 DEF 456 ... ... Source: [[http://www.devx.com/codemag/Article/40833|DevX: Flexible and Powerful Data Binding with WPF, Part 2]] And in C# you can access that instance as well: void Window_Loaded(object sender, RoutedEventArgs args) { DataConnection dc1 = this.FindResource("emp") as DataConnection; DataConnection dc2 = this.Resources["emp"] as DataConnection; } ''FindResource("emp")'' will search the element's resource dictionary as well as any parent elements' resource dictionaries and the application resources. ''Resources["emp"]'' will search only the resource dictionary of that element. The documentation recommends the first approach for normal resource lookups, but provides the second approach for when you are retrieving resources from a "known resource dictionary location ... to avoid the possible performance and scope implications of run-time key lookup. Source: [[http://stackoverflow.com/questions/2039425/access-xaml-instantiated-object-from-c|Access XAML instantiated object from C#]] == Connecting to a Local Property == You must use Dependency Properties to connect to a local property using data binding. First, define the Dependency Property in C#: using System.Windows; namespace SOTCBindingValidation { public partial class Window1 : Window { public static readonly DependencyProperty IPAddressProperty = DependencyProperty.Register("IPAddress", typeof(string), typeof(Window1), new UIPropertyMetadata("1.1.1.1")); public string IPAddress { get { return (string)GetValue(IPAddressProperty); } set { SetValue(IPAddressProperty, value); } } public Window1() { InitializeComponent(); } } } Then make a reference to the required property in XAML: Enter An IPv4 Address: Source: [[http://www.switchonthecode.com/tutorials/wpf-tutorial-binding-validation-rules|WPF - Binding Validation Rules]] == Connecting to an XML File == XML File: Acme's 12th Annual Continuing Education Workshop 12 AcmeWorkshop12 Orlando Marriott Lake Mary 1501 International Parkway Lake Mary FL 32746 407.995.1100 800.380.7724 407.995.1101 www.marriotthotels.com 2011/01/14 2011/01/15 Premium 100 Standard 200 Other 200 Acme's 13th Annual Continuing Education Workshop 13 AcmeWorkshop13 Orlando Marriott Lake Mary 1501 International Parkway Lake Mary FL 32746 407.995.1100 800.380.7724 407.995.1101 www.marriotthotels.com 2012/01/24 2012/01/25 Premium 100 Standard 200 Other 200 Data binding for a ''DataGrid'': ... Record Details Last Name First Name ID ''ucPatientInfo.xaml.cs'': using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace DataBinding.Patient { /// /// Interaction logic for ucDataBinding.xaml /// public partial class ucPatientInfo : UserControl { private TPatientListOC patlist = new TPatientListOC(); public ucPatientInfo() { InitializeComponent(); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { patlist = (TPatientListOC)FindResource("PatientListOCDS"); //patlist.PopulateList(); } private void btnLoadList_Click(object sender, RoutedEventArgs e) { patlist.PopulateList(); } private void btnAdd_Click(object sender, RoutedEventArgs e) { if (txtLastName.Text != "" && txtFirstName.Text != "" && txtID.Text != "") { TPatientInfo pat = new TPatientInfo(); pat.LastName = txtLastName.Text; pat.FirstName = txtFirstName.Text; pat.ID = Convert.ToInt32(txtID.Text); patlist.Add(pat); } else { MessageBox.Show("Please fill in all fields with valid data before adding record."); } } private void btnClearList_Click(object sender, RoutedEventArgs e) { patlist.Clear(); } private void btnDeleteSelection_Click(object sender, RoutedEventArgs e) { patlist.RemoveAt(lstPatientList.SelectedIndex); } } } === Programmatic Method === Programmaticaly create an instance to a list of objects, then programmatically databind a ''ListBox'' to it. Note that the data binding is set to the ''ListBox'''s ''DataContext'', and requires a ''DataTemplate'' defined for it to work. ''ucPatientInfo.xaml'': Patient List Record Details Last Name First Name ID ''ucPatientInfo.xaml.cs'': using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace DataBinding.Patient { /// /// Interaction logic for ucDataBinding.xaml /// public partial class ucPatientInfo : UserControl { private TPatientListOC patlist = new TPatientListOC(); public ucPatientInfo() { InitializeComponent(); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { DataBinding(); } //--------------------------------------------------------------------------- // Create Data Binding programmatically. //--------------------------------------------------------------------------- private void DataBinding() { Binding bindListItems = new Binding(); bindListItems.Source = patlist; bindListItems.Mode = BindingMode.OneWay; // TwoWay does not work for ListBox lstPatientList.SetBinding(ListBox.ItemsSourceProperty, bindListItems); } private void btnLoadList_Click(object sender, RoutedEventArgs e) { patlist.PopulateList(); } private void btnAdd_Click(object sender, RoutedEventArgs e) { if (txtLastName.Text != "" && txtFirstName.Text != "" && txtID.Text != "") { TPatientInfo pat = new TPatientInfo(); pat.LastName = txtLastName.Text; pat.FirstName = txtFirstName.Text; pat.ID = Convert.ToInt32(txtID.Text); patlist.Add(pat); } else { MessageBox.Show("Please fill in all fields with valid data before adding record."); } } private void btnClearList_Click(object sender, RoutedEventArgs e) { patlist.Clear(); } private void btnDeleteSelection_Click(object sender, RoutedEventArgs e) { patlist.RemoveAt(lstPatientList.SelectedIndex); } } } == IValueConverter == Data binding to properties that do not match the type require a value converter (using ''IValueConverter''). For example, converting from ''Visibility'' (''Visible'', ''Hidden'', or ''Collapsed'') into ''bool'': // using System.Windows.Data; // Found in PresentationFramework assembly public class TBoolToVisibilityConverter: IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Visibility _visibility; if ((bool)value == true) { _visibility = Visibility.Visible; } else { _visibility = Visibility.Collapsed; } return _visibility; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } Use it as: ... Bluetooth Support ... A value converter for an image path that needs the full path prefixed to it: // using System.Windows.Data; // Found in PresentationFramework assembly public class TImgPathConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string str = (string)value; return "pack://application:,,,/AHI.Products.Specifications;component/" + str; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } ... Shell/Case View ... Microsoft's example: // using System.Windows; // Found in WindowsBase assembly // using System.Windows.Data; // Found in PresentationFramework assembly [ValueConversion(typeof(DateTime), typeof(String))] public class DateConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { DateTime date = (DateTime)value; return date.ToShortDateString(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string strValue = value as string; DateTime resultDateTime; if (DateTime.TryParse(strValue, out resultDateTime)) { return resultDateTime; } return DependencyProperty.UnsetValue; } } XML: Start Date: Source: [[http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx|MSDN: IValueConverter Interface]] === IValueConverter using Parameters === ==== Example 1 ==== XAML: C#: public class StringFormatConverter:IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string formatString = parameter.ToString(); return String.Format("{0:" + formatString + "}", value); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException("This Convert supports only OneWay binding"); } #endregion } ==== Example 2 ==== XAML: Customizing the PropertyViewer is also easy: And the C# code behind: public class PropertyViewer : IValueConverter { /// /// Implements IValueConverter.Convert. /// public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // Fetch parameters var propertyInfos = (null != value) ? value.GetType().GetProperties() : new PropertyInfo[0]; var propertyNames = (null != parameter) ? parameter.ToString().Split() : new string[0]; // Prepare a collection to return var propertyDetails = new List(); // No names specified (or no value/properties available) if ((0 == propertyNames.Length) || (0 == propertyInfos.Length)) { // Add all properties to the collection foreach (var propertyInfo in propertyInfos) { propertyDetails.Add(new PropertyDetails(GetPropertyName(propertyInfo), GetPropertyValue(propertyInfo, value))); } } else { // For each property name specified foreach (var propertyName in propertyNames) { // Try to match the name against each property in turn bool found = false; foreach (var propertyInfo in propertyInfos) { if (propertyName == propertyInfo.Name) { // Match; add the property to the collection propertyDetails.Add(new PropertyDetails(GetPropertyName(propertyInfo), GetPropertyValue(propertyInfo, value))); found = true; break; } } if (!found && (0 < propertyName.Length)) { // No matches (and not an empty name); throw an exception throw new ArgumentException("Property \"" + propertyName + "\" does not exist on object " + value + "."); } } } // Return the collection return propertyDetails; } /// /// Implements IValueConverter.ConvertBack. /// public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException("PropertyViewer does not use ConvertBack."); } /// /// Gets the name of the specified property. /// /// property /// name private static string GetPropertyName(PropertyInfo propertyInfo) { // Look for DisplayNameAttribute var displayNameAttributes = propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true); // Return first DisplayNameAttribute.DisplayName or property name if none present return (0 < displayNameAttributes.Length) ? ((DisplayNameAttribute)(displayNameAttributes[0])).DisplayName : propertyInfo.Name; } /// /// Gets the value of the specified property for an instance. /// /// property /// instance /// value private static object GetPropertyValue(PropertyInfo propertyInfo, object instance) { try { // Return instance's value return propertyInfo.GetValue(instance, null); } catch (TargetParameterCountException) { // Likely an indexer (ex: Array.Items); skip complex properties here return null; } } } Source: [[http://blogs.msdn.com/b/delay/archive/2008/05/04/ivalueconverter-the-swiss-army-knife-of-bindings-propertyviewer-sample-is-a-wpf-silverlight-visualization-and-debugging-aid.aspx|IValueConverter: The Swiss Army Knife of Bindings...]] == Multi-Binding == To display 2 different variables in a same field (eg: 3.14 = May 5, 2012): = Debugging = == Add Tracing to Output Window == 1. Add ''diag:PresentationTraceSources.TraceLevel=High'' to your binding. For example: 2. Add a value converter to the binding, to be able to put a break point in debugger. See more: * [[https://spin.atomicobject.com/2013/12/11/wpf-data-binding-debug/|How To Debug Data Binding Issues in WPF]] == Enable Debug Output == * Enable WPF debug output. In Visual Studio, Options > Debugging > Output Window > WPF Trace Settings > Data Binding > All. * Add a high TraceLevel to your binding: PresentationTraceSources.SetTraceLevel(NewBinding, PresentationTraceLevel.High); * Run application, and review log in "Output" tab in Visual Studio. * Add ''System.Diagnostics'' entry to ''app.exe.config''. See: * [[swdev:dotnet:debugging|Debugging for .NET]] * [[http://www.thejoyofcode.com/System.Diagnostics_hidden_SourceLevels.aspx|The Joy of Code: System.Diagnostics Hidden SourceLevels]] * [[http://msdn.microsoft.com/en-us/library/aa345169.aspx|MSDN: PresentationTraceSources Class]] * [[http://msdn.microsoft.com/en-us/library/system.diagnostics.presentationtracesources.settracelevel.aspx|MSDN: SetTraceLevels]] * [[http://msdn.microsoft.com/en-us/library/6w20x90k.aspx|MSDN: EventLog.WriteEntry method]] * [[http://stackoverflow.com/questions/4026543/is-there-a-good-tool-for-debugging-xamls-databinding-behavior-errors-at-runtim|Tools for Debugging Data Binding at runtime]] * [[http://bea.stollnitz.com/blog/?p=52|Bea Stollnitz: How can I debug WPF bindings?]] * [[https://spin.atomicobject.com/2013/12/11/wpf-data-binding-debug/|How To Debug Data Binding Issues in WPF]] = See Also = * [[http://msdn2.microsoft.com/en-us/library/ms752347(VS.85).aspx|MSDN Data Binding Overview]] * [[http://msdn.microsoft.com/en-us/library/ms752039.aspx|MSDN Data Binding How-to Topics]] * [[http://msdn.microsoft.com/en-us/library/system.windows.data.objectdataprovider.aspx|MSDN ObjectDataProvider Class]] * [[http://msdn.microsoft.com/en-us/library/system.windows.data.xmldataprovider.aspx|MSDN XmlDataProvider Class]] * [[http://msdn.microsoft.com/en-us/library/aa480224.aspx|MSDN WPF Data Binding (Part 1)]] * [[http://www.wpfdude.com/articles/BindingToElement.aspx|WPF Basics - Binding to a Property of Another Element]] * [[http://blogs.msdn.com/b/wpfsdk/archive/2006/10/19/wpf-basic-data-binding-faq.aspx|WPF Basic Data Binding]] * [[http://bea.stollnitz.com/blog/?p=22|Why Should I Use ObjectDataProvider?]] * [[http://bea.stollnitz.com/blog/?p=5|Binding and DataTemplates]] * [[http://www.codeproject.com/KB/WPF/GuidedTourWPF_3.aspx|A Guided Tour of WPF - (Part 3) Data Binding]] * [[http://www.devx.com/codemag/Article/40833|DevX: Flexible and Powerful Data Binding in WPF (Part 2)]] * [[http://odetocode.com/Articles/740.aspx|OdeToCode: Databinding in Silverlight]] * [[http://joshsmithonwpf.wordpress.com/2007/06/04/binding-to-xml|John Smith on WPF: Binding to XML]] * ObservableCollection and Item PropertyChanged * [[http://stackoverflow.com/questions/901921/observablecollection-and-item-propertychanged|StackOverflow: ObservableCollection and Item PropertyChanged]] * [[http://stackoverflow.com/questions/1003344/observablecollection-propertychanged-event|StackOverflow: ObservableCollection PropertyChanged event]] * [[http://forums.silverlight.net/forums/p/221473/530822.aspx#530822|Implement INotifyCollectionChanged with MVVM]]