DataContext im data binding-Konzept (WPF)

Der DataContext ist die default Quelle Deiner bindings. Ist er gesetzt, wird er innerhalb der Control-Hierarchie (beginnend mit Window) nach unten vererbt. Jedes WPF-Control hat sein eigenes DataContext-property, sodass man auf jeder Vererbungsebene die Vererbungshierarchie durchbrechen und ab dort eine neue Vererbungshierarchie etablieren kann. Wird der DataContext nicht gesetzt ist er null.

Der DataContext kann auf verschiedene Arten an verschiedenen Stellen erstellt werden (was es nicht gerade leichter macht, den Gesamtüberblick zu behalten):

DataContext via Window.DataContext

<Window x:Class="SampleApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" DataContext="{Binding Employee}">

bzw.

<Window x:Class="Example.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="clr-namespace:Example" Title="Example" Height="300" Width="300" Name="Main">

 <Window.DataContext>
     <StaticResource ResourceKey="data"/>
 </Window.DataContext>

Ziemlich gute Darstellung des Zusammenspiels von Window.DataContext, Window.Resources und einem WPF-Control: http://stackoverflow.com/a/1959701/1777526

DataContext in einem untergeordneten WPF-control

<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">

Quelle

DataContext in der Codebehind-Datei

    public MainWindow()
    {
        (...)
        gridOfNames.DataContext = new ParameterDataSource();
        (...)
    }

Häufig wird die zu entwickelnde GUI selbst als DataContext gesetzt, wobei es zwei Wege gibt:

1.) im XAML

<Window x:Class="MyClass"
  Title="{Binding windowname}"
  DataContext="{Binding RelativeSource={RelativeSource Self}}"
  Height="470" Width="626">

weiterführende Quelle

2.) im Codebehind

public class MyWindow : Window {

    public MyWindow() {
        InitializeComponents();
        DataContext = this;
    }   
}

Weiterführende Quelle mit gutem Anwendungsbeispiel

Binding-Quellen jenseits vom DataContext

Braucht man eine Binding-Quelle nur für ein UI-control (und nicht für dessen Nachkommencontrols in der Vererbungshierarchie) kann man diese individuell setzen. Ein gg.falls existierender DataContext wird dadurch für dieses UI-Control überschrieben. Z.B. mit ‚ElementName‘ welches direkt zu einem anderen UI-Element bindet:

<Window x:Class="WpfTutorialSamples.DataBinding.HelloBoundWorldSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="HelloBoundWorldSample" Height="110" Width="280">
    <StackPanel Margin="10">
         <TextBox Name="txtValue" />
         <WrapPanel Margin="0,10">
             <TextBlock Text="Value: " FontWeight="Bold" />
             <TextBlock Text="{Binding Path=Text, ElementName=txtValue}" />
         </WrapPanel>
     </StackPanel>
</Window>

… oder mit dem Source-Property, welches z.B. zu einer Window.Ressource bindet:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:src="clr-namespace:SDKSample"
  SizeToContent="WidthAndHeight"
  Title="Simple Data Binding Sample">

  <Window.Resources>
    <src:Person x:Key="myDataSource" PersonName="Joe"/>
  </Window.Resources>
  (...)
  <TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>
  (...)
</Window>

Data binding XAML-Syntax

Die Data Binding XAML-Syntax krankt an zu vielen impliziten und schlecht benannten Elementen. Diese machen es jedem schwer, die Funktionalität zumindest im Groben zu verstehen, ohne tiefer ins Thema einzutauchen. Daher im Folgenden eine Aufstellung an Data Binding Notationen mit Erläuterung:

Empty binding syntax

<ListBox ItemsSource="{Binding}"/>

In diesem Fall erbt ListBox den DataContext von einem übergeordneten DockPanel-Element (wird in diesem Beispiel nicht gezeigt). Wenn der Pfad nicht angegeben wurde, erfolgt die Bindung standardmäßig an das gesamte Objekt. (Quelle)

Path-property, explizit

<ListBox ItemsSource="{Binding Path=MyProperty}"/>

Aus dem DataContext, der weiter oben im XAML gesetzt wird, wird ein Property an die ListBox gebunden.

Path-property, implizit

<ListBox ItemsSource="{Binding MyProperty}"/>

Ist syntaktisch gleichbedeutend mit `Path-property, explizit` (Quelle).

Weiterführende Links:
https://msdn.microsoft.com/en-us/library/system.windows.data.binding.path.aspx
https://msdn.microsoft.com/en-us/library/ms742451.aspx

Einfachstes Beispiel für data-binding mit enum

Es gibt einige Stackoverflow-Threads (1 und 2), die sich damit beschäftigen, ein enum als Datenquelle für ein WPF-Control mit Hilfe von data-binding zu nutzen. Die meisten Lösungsansätze sind ziemlicher overkill und der Code nicht exakt ausgeführt, so dass sie nicht leicht zum Laufen gebracht werden können. Daher folgt nun ein ziemlich triviales Beispiel, welches exakt so läuft, wie es hier steht und aus nur zwei kleinen Dateien besteht:

In Visual Studio:
File -> New -> Project
Installed -> Templates -> Visual C# -> Windows -> WPF Application

1.) MainWindow.xaml.cs kann gelöscht werden.

2.) Der Code in MainWindow.xaml wird ersetzt durch:

<Window 
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:System="clr-namespace:System;assembly=mscorlib"
 xmlns:local="clr-namespace:MyExampleApplication"
 Title="Bind to Enum" Width="250" Height="100">
    <Window.Resources>
        <ObjectDataProvider x:Key="myEnumValues" MethodName="GetValues" ObjectType="{x:Type System:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:MyExampleEnum"/>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <ComboBox ItemsSource="{Binding Source={StaticResource myEnumValues}}" />
    </Grid>
</Window>

3.) Neue Datei ‚MyExampleEnum.cs‘ erzeugen und folgenden Code eintragen:

namespace MyExampleApplication
{
    public enum MyExampleEnum
    {
        Red,
        Green,
        Yellow
    }
}

Und so sieht MyExampleApplication dann im Ergebnis aus:

enum data-binding wpf control