Ricerca…


Sintassi

  • {Binding PropertyName} è equivalente a {Binding Path = PropertyName}
  • {Binding Path = SomeProperty.SomeOtherProperty.YetAnotherProperty}
  • {Binding Path = SomeListProperty [1]}

Parametri

Parametro Dettagli
Sentiero Specifica il percorso per associare a. Se non specificato, si collega a DataContext stesso.
UpdateSourceTrigger Specifica quando l'origine dell'associazione ha il suo valore aggiornato. Il valore predefinito è LostFocus . Il valore più utilizzato è PropertyChanged .
Modalità In genere OneWay o TwoWay . Se non specificato dal TwoWay viene TwoWay su OneWay meno che la destinazione vincolante non richieda che sia TwoWay . Si verifica un errore quando TwoWay viene utilizzato per collegarsi a una proprietà readonly, ad esempio OneWay deve essere impostato in modo esplicito quando si TextBox.Text una proprietà stringa di sola lettura a TextBox.Text .
fonte Consente l'utilizzo di StaticResource come origine di binding anziché DataContext corrente.
RelativeSource Consente l'utilizzo di un altro elemento XAML come origine di associazione anziché DataContext corrente.
ElementName Consente l'utilizzo di un elemento XAML denominato come origine di associazione anziché DataContext corrente.
FallbackValue Se l'associazione fallisce, questo valore viene fornito alla destinazione vincolante.
TargetNullValue Se il valore dell'origine dell'associazione è null , questo valore viene fornito alla destinazione vincolante.
Converter Specifica il convertitore StaticResource utilizzato per convertire il valore dell'associazione, ad esempio, converte un valore booleano in un elemento enumerazione Visibility .
ConverterParameter Specifica un parametro facoltativo da fornire al convertitore. Questo valore deve essere statico e non può essere associato.
StringFormat Specifica una stringa di formato da utilizzare quando si visualizza il valore associato.
Ritardo (WPF 4.5+) Specifica un ritardo in milliseconds affinché il binding aggiorni BindingSource in ViewModel . Deve essere utilizzato con Mode=TwoWay e UpdateSourceTrigger=PropertyChanged per avere effetto.

Osservazioni

UpdateSourceTrigger

Per impostazione predefinita, WPF aggiorna l'origine dell'associazione quando il controllo perde lo stato attivo. Tuttavia, se esiste un solo controllo che può ottenere l' UpdateSourceTrigger=PropertyChanged comune negli esempi, è necessario specificare UpdateSourceTrigger=PropertyChanged perché gli aggiornamenti funzionino.

Vorrai utilizzare PropertyChanged come trigger su molti collegamenti bidirezionali, a meno che l'aggiornamento dell'origine dell'assegnazione su ogni sequenza di tasti sia costoso o la convalida dei dati in tempo reale non sia desiderabile.

L'uso di LostFocus ha uno sfortunato effetto collaterale: premendo Invio per inviare un modulo utilizzando un pulsante contrassegnato con IsDefault non si aggiorna la proprietà di backup del binding, annullando in modo efficace le modifiche. Fortunatamente, esistono alcuni soluzioni alternative .

Si noti inoltre che, a differenza di UWP, WPF (4.5+) ha anche la proprietà Delay in binding, che potrebbe essere sufficiente per alcuni binding con impostazioni di intelligenza minore solo locali o semplici, come alcune validazioni di TextBox .

Converti un valore booleano in visibilità

Questo esempio nasconde il riquadro rosso (bordo) se la casella di controllo non è selezionata facendo uso di un IValueConverter .

Nota: il BooleanToVisibilityConverter utilizzato nell'esempio seguente è un convertitore di valori incorporato, ubicato nello spazio dei nomi System.Windows.Controls.

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>

Definizione del DataContext

Per lavorare con i binding in WPF, è necessario definire un DataContext . DataContext indica i collegamenti da cui ottenere i dati per impostazione predefinita.

<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>

È inoltre possibile impostare DataContext tramite code-behind, ma vale la pena notare che XAML IntelliSense è piuttosto esigente: è necessario impostare DataContext fortemente tipizzato in XAML per IntelliSense per suggerire le proprietà disponibili per l'associazione.

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new HelloWorldViewModel();
    }
}

Mentre ci sono framework per aiutarti a definire il tuo DataContext in un modo più flessibile (es. MVVM Light ha un viewmodel locator che usa l' inversione del controllo ), usiamo il metodo rapido e sporco ai fini di questo tutorial.

È possibile definire un DataContext per quasi tutti gli elementi visivi in ​​WPF. DataContext è generalmente ereditato dagli antenati nella struttura ad albero visuale a meno che non sia stato esplicitamente ignorato, ad esempio all'interno di un ContentPresenter.

Implementazione di INotifyPropertyChanged

INotifyPropertyChanged è un'interfaccia utilizzata dalle fonti di binding (ovvero il DataContext) per consentire all'interfaccia utente o ad altri componenti di sapere che una proprietà è stata modificata. WPF aggiorna automaticamente l'interfaccia utente quando rileva l'evento PropertyChanged generato. È auspicabile che questa interfaccia sia implementata su una classe base che tutti i tuoi viewmodels possano ereditare.

In C # 6, questo è tutto ciò di cui hai bisogno:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

Ciò consente di invocare NotifyPropertyChanged in due modi diversi:

  1. NotifyPropertyChanged() , che genererà l'evento per il setter che lo invoca, grazie all'attributo CallerMemberName .
  2. NotifyPropertyChanged(nameof(SomeOtherProperty)) , che genererà l'evento per SomeOtherProperty.

Per .NET 4.5 e versioni successive con C # 5.0, è possibile utilizzare invece:

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));
        }
    }
}

Nelle versioni di .NET precedenti alla 4.5, è necessario accontentarsi dei nomi di proprietà come costanti di stringa o di una soluzione che utilizza espressioni .


Nota: è possibile associare a una proprietà di un "vecchio oggetto C # semplice" (POCO) che non implementa INotifyPropertyChanged e osservare che le associazioni funzionano meglio del previsto. Questa è una funzionalità nascosta in .NET e dovrebbe probabilmente essere evitata. Soprattutto perché causerà perdite di memoria quando la Mode di rilegatura non è OneTime (vedi qui ).

Perché l'aggiornamento dell'associazione non implementa INotifyPropertyChanged?

Associare alla proprietà di un altro elemento denominato

È possibile associare a una proprietà su un elemento denominato, ma l'elemento denominato deve essere incluso nell'ambito.

<StackPanel>
    <CheckBox x:Name="MyCheckBox" IsChecked="True" />
    <TextBlock Text="{Binding IsChecked, ElementName=MyCheckBox}" />
</StackPanel>

Legarsi alla proprietà di un antenato

È possibile eseguire il binding a una proprietà di un antenato nell'albero visivo utilizzando un'associazione RelativeSource . Il controllo più vicino più in alto nell'albero visivo che ha lo stesso tipo o è derivato dal tipo specificato verrà utilizzato come origine del legame:

<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 questo esempio, Button1 ha uno sfondo grigio perché l'antenato Grid più vicino ha uno sfondo grigio. Button2 ha uno sfondo bianco perché l'antenato più prossimo derivato da FrameworkElement è lo StackPanel bianco.

Esempio di associazione RelativeSource

Associazione di più valori con un MultiBinding

Il MultiBinding consente di associare più valori alla stessa proprietà. Nell'esempio seguente più valori sono associati alla proprietà Text di una casella di testo e formattati utilizzando la proprietà StringFormat.

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="{}{0} {1}">
            <Binding Path="User.Forename"/>
            <Binding Path="User.Surname"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Oltre a StringFormat , è possibile utilizzare anche IMultiValueConverter per convertire i valori dai binding in un valore per la destinazione di MultiBinding.

Tuttavia, MultiBindings non può essere annidato.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow