wpf
Einführung in die WPF-Datenbindung
Suche…
Syntax
- {Binding PropertyName} entspricht {Bindungspfad = PropertyName}
- {Bindungspfad = SomeProperty.SomeOtherProperty.YetAnotherProperty}
- {Bindungspfad = SomeListProperty [1]}
Parameter
Parameter | Einzelheiten |
---|---|
Pfad | Gibt den Pfad an, an den gebunden werden soll. Wenn nicht angegeben, bindet an den DataContext selbst. |
UpdateSourceTrigger | Gibt an, wann der Wert der Bindungsquelle aktualisiert wurde. LostFocus . Der am häufigsten verwendete Wert ist PropertyChanged . |
Modus | Normalerweise OneWay oder TwoWay . Wenn die Bindung dies nicht TwoWay , wird standardmäßig OneWay sofern das Bindungsziel nicht TwoWay . Ein Fehler tritt auf, wenn TwoWay verwendet wird , um eine Nur - Lese - Eigenschaft zu binden, zB OneWay explizit festgelegt werden muß , wenn eine Nur - Lese - String - Eigenschaft zur Bindung TextBox.Text . |
Quelle | Ermöglicht die Verwendung einer StaticResource als Bindungsquelle anstelle des aktuellen DataContext. |
RelativeSource | Ermöglicht die Verwendung eines anderen XAML-Elements als Bindungsquelle anstelle des aktuellen DataContext. |
ElementName | Ermöglicht die Verwendung eines benannten XAML-Elements als Bindungsquelle anstelle des aktuellen DataContext. |
FallbackValue | Wenn die Bindung fehlschlägt, wird dieser Wert dem Bindungsziel bereitgestellt. |
TargetNullValue | Wenn die Bindungsquelle Wert ist null , wird dieser Wert an das Bindungsziel bereitgestellt. |
Konverter | Gibt die Konverter- StaticResource , die zum Konvertieren des Bindungswerts verwendet wird, z. B. Konvertieren eines Boolean in ein Visibility . |
ConverterParameter | Gibt einen optionalen Parameter an, der dem Konverter zur Verfügung gestellt werden soll. Dieser Wert muss statisch sein und kann nicht gebunden werden. |
StringFormat | Gibt eine Formatzeichenfolge an, die beim Anzeigen des gebundenen Werts verwendet werden soll. |
Verzögern | (WPF 4.5+) Gibt eine Verzögerung in milliseconds für die Bindung zum Aktualisieren der BindingSource im ViewModel . Dies muss mit Mode=TwoWay und UpdateSourceTrigger=PropertyChanged , um wirksam zu werden. |
Bemerkungen
UpdateSourceTrigger
Standardmäßig aktualisiert WPF die Bindungsquelle, wenn das Steuerelement den Fokus verliert. Wenn es jedoch nur ein Steuerelement gibt, das den Fokus erhält - was in Beispielen üblich ist - müssen Sie UpdateSourceTrigger=PropertyChanged
angeben, UpdateSourceTrigger=PropertyChanged
die Aktualisierungen funktionieren.
Sie sollten PropertyChanged
als Auslöser für viele bidirektionale Bindungen verwenden, es sei denn, das Aktualisieren der Bindungsquelle bei jedem Tastendruck ist kostspielig oder die Live-Datenvalidierung ist unerwünscht.
Die Verwendung von LostFocus
hat einen unglücklichen Nebeneffekt: Wenn Sie die LostFocus
drücken, um ein Formular mit einer mit IsDefault
markierten Schaltfläche zu IsDefault
wird die Eigenschaft, die Ihre Bindung unterstützt, nicht aktualisiert. Glücklicherweise gibt es einige Problemumgehungen .
Bitte beachten Sie auch, dass WPF (4.5+) im Gegensatz zu UWP auch die Delay
Eigenschaft in Bindings hat, die für einige Bindings mit lokalen Einstellungen oder einfachen geringfügigen Intelligenzeinstellungen wie einigen TextBox
Validierungen gerade ausreicht.
Konvertieren Sie einen Booleschen Wert in einen Sichtbarkeitswert
In diesem Beispiel wird das rote Feld (Rahmen) IValueConverter
wenn das Kontrollkästchen nicht mithilfe eines IValueConverter
.
Hinweis: Der im folgenden Beispiel verwendete BooleanToVisibilityConverter
ist ein integrierter Wertkonverter, der sich im Namespace System.Windows.Controls befindet.
XAML:
<Window x:Class="StackOverflowDataBindingExample.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">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="VisibleIfTrueConverter" />
</Window.Resources>
<StackPanel>
<CheckBox x:Name="MyCheckBox"
IsChecked="True" />
<Border Background="Red" Width="20" Height="20"
Visibility="{Binding Path=IsChecked,ElementName=MyCheckBox, Converter={StaticResource VisibleIfTrueConverter}}" />
</StackPanel>
</Window>
DataContext definieren
Um mit Bindungen in WPF arbeiten zu können, müssen Sie einen DataContext definieren. Der DataContext teilt Bindungen mit, woher ihre Daten standardmäßig abgerufen werden.
<Window x:Class="StackOverflowDataBindingExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflowDataBindingExample"
xmlns:vm="clr-namespace:StackOverflowDataBindingExample.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<vm:HelloWorldViewModel />
</Window.DataContext>
...
</Window>
Sie können DataContext auch über Code-Behind einstellen. Beachten Sie jedoch, dass XAML IntelliSense etwas wählerisch ist: In XAML muss ein stark typisierter DataContext festgelegt werden, damit IntelliSense Eigenschaften für die Bindung vorschlagen kann.
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new HelloWorldViewModel();
}
}
Zwar gibt es Frameworks, mit denen Sie DataContext flexibler definieren können (z. B. MVVM Light hat einen Viewmodel-Locator, der die Umkehrung der Steuerung verwendet ). In diesem Lernprogramm verwenden wir jedoch die schnelle und unreine Methode.
Sie können einen DataContext für nahezu jedes visuelle Element in WPF definieren. Der DataContext wird in der Regel von Vorfahren im visuellen Baum geerbt, sofern er nicht explizit überschrieben wurde, z. B. in einem ContentPresenter.
INotifyPropertyChanged implementieren
INotifyPropertyChanged
ist eine Schnittstelle, die von Bindungsquellen (dh dem DataContext) verwendet wird, um die Benutzeroberfläche oder andere Komponenten INotifyPropertyChanged
, dass eine Eigenschaft geändert wurde. WPF aktualisiert die Benutzeroberfläche automatisch für Sie, wenn das PropertyChanged
Ereignis ausgelöst wird. Es ist wünschenswert, dass diese Schnittstelle in einer Basisklasse implementiert ist, von der alle Viewmodels erben können.
In C # 6 ist dies alles, was Sie brauchen:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Auf diese Weise können Sie NotifyPropertyChanged
auf zwei verschiedene Arten aufrufen:
-
NotifyPropertyChanged()
, wodurch das Ereignis für den SetterNotifyPropertyChanged()
wird, der es aufgrund des Attributs CallerMemberName aufruft . -
NotifyPropertyChanged(nameof(SomeOtherProperty))
, wodurch das Ereignis für SomeOtherProperty ausgelöst wird.
Für .NET 4.5 und höher mit C # 5.0 kann dies stattdessen verwendet werden:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] string name = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
In .NET-Versionen vor 4.5 müssen Sie Eigenschaftsnamen als Zeichenfolgekonstanten oder eine Lösung mit Ausdrücken festlegen .
Anmerkung: Es ist möglich, an eine Eigenschaft eines "plain old C # object" (POCO) zu binden, das INotifyPropertyChanged
nicht implementiert, und zu beobachten, dass die Bindungen besser funktionieren als erwartet. Dies ist eine versteckte Funktion in .NET und sollte wahrscheinlich vermieden werden. OneTime
insbesondere für Speicherlecks, wenn der Mode
der Bindung nicht OneTime
(siehe hier ).
Warum wird die Bindung ohne Implementierung von INotifyPropertyChanged aktualisiert?
Binden an die Eigenschaft eines anderen benannten Elements
Sie können an eine Eigenschaft eines benannten Elements binden, das benannte Element muss jedoch im Gültigkeitsbereich liegen.
<StackPanel>
<CheckBox x:Name="MyCheckBox" IsChecked="True" />
<TextBlock Text="{Binding IsChecked, ElementName=MyCheckBox}" />
</StackPanel>
Binden an Eigentum eines Vorfahren
Sie können an eine Eigenschaft eines Vorfahren in der visuellen Baumstruktur binden, indem Sie eine RelativeSource
Bindung verwenden. Das nächstgelegene Steuerelement oberhalb des visuellen Baums, das denselben Typ hat oder von dem von Ihnen angegebenen Typ abgeleitet ist, wird als Quelle der Bindung verwendet:
<Grid Background="Blue">
<Grid Background="Gray" Margin="10">
<Border Background="Red" Margin="20">
<StackPanel Background="White" Margin="20">
<Button Margin="10" Content="Button1" Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}" />
<Button Margin="10" Content="Button2" Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}}" />
</StackPanel>
</Border>
</Grid>
</Grid>
In diesem Beispiel hat Button1 einen grauen Hintergrund, da der nächste Vorläufer des Grid
einen grauen Hintergrund hat. Button2 hat einen weißen Hintergrund, da der nächstgelegene Vorfahr von FrameworkElement
das weiße StackPanel
.
Mehrere Werte mit einer MultiBinding binden
Das MultiBinding ermöglicht das Binden mehrerer Werte an dieselbe Eigenschaft. Im folgenden Beispiel werden mehrere Werte an die Text-Eigenschaft eines Textfelds gebunden und mit der StringFormat-Eigenschaft formatiert.
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="User.Forename"/>
<Binding Path="User.Surname"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Neben StringFormat
kann ein IMultiValueConverter
auch verwendet werden, um die Werte der Bindungen in einen Wert für das MultiBinding-Ziel zu konvertieren.
MultiBindings können jedoch nicht geschachtelt werden.