« Binding » : différence entre les versions
(2 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 90 : | Ligne 90 : | ||
<ControlTemplate TargetType="{x:Type Button}"> | <ControlTemplate TargetType="{x:Type Button}"> | ||
<!-- liaison du Text de la TextBox avec le Content du Button --> | <!-- liaison du Text de la TextBox avec le Content du Button --> | ||
<TextBlock Text="{TemplateBinding | <TextBlock Text="{TemplateBinding Content}"/> | ||
</ControlTemplate> | </ControlTemplate> | ||
</Button.Template> | </Button.Template> | ||
</Button> | </Button> | ||
<Style BasedOn="{StaticResource {x:Type Button}}" | |||
TargetType="Button"> | |||
<Setter Property="Background" Value="Blue" /> | |||
<Setter Property="Template"> | |||
<Setter.Value> | |||
<ControlTemplate TargetType="{x:Type Button}"> | |||
<!-- link the Background to the one defined in the style --> | |||
<TextBlock Background="{TemplateBinding Background}" /> | |||
</ControlTemplate> | |||
</Setter.Value> | |||
</Setter> | |||
</Style> | |||
</kode> | </kode> | ||
Ligne 225 : | Ligne 238 : | ||
} | } | ||
</filebox> | </filebox> | ||
= StringFormat = | |||
<kode lang='xaml'> | |||
<TextBlock Text="{Binding Name, StringFormat=Name: {0}}" /> | |||
<TextBlock Text="{Binding Date, ConverterCulture='fr-FR', StringFormat=Date: {0:D}}" /> | |||
</kode> |
Dernière version du 19 octobre 2021 à 21:48
Links
Objet métier ↔ objet graphique : INotifyPropertyChange
On incrémente la valeur Entier lors du click sur le bouton.
Comme la classe Numéro implémente INotifyPropertyChanged et que la propriété Entier raise l’évènement PropertyChanged lorsque sa valeur change, le TextBlock qui est bindé sur la propriété Entier est notifié du changement et peut mettre à jour la valeur Text.
public partial class MainWindow : Window { public Numéro Numéro { get; set; } private void Button_Click(object sender, RoutedEventArgs e) { Numéro.Entier++; } public MainWindow() { InitializeComponent(); Numéro = new Numéro(); this.DataContext = this; } } public class Numéro : INotifyPropertyChanged { private int _entier; public int Entier { get { return _entier; } set { _entier = value; OnPropertyChanged("Entier"); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } |
<Window x:Class="WpfApplication.MainWindow" ... > <TextBlock Text="{Binding Path=Numéro.Entier}"></TextBlock> <Button Click="Button_Click">Click</Button> |
Objet graphique ↔ objet graphique : Dependancy Property
<!-- Récupère la valeur Texte de tbx et modifie la valeur Texte du TextBlock --> <TextBlock Text="{Binding ElementName=tbx, Path=Text, Mode=OneWay}"></TextBlock> <TextBox x:Name="tbx"></TextBox> <!-- Pousse la valeur Texte du TextBox et modifie la valeur Texte de tbk --> <TextBlock x:Name="tbk"></TextBlock> <TextBox Text="{Binding ElementName=tbk, Path=Text, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"></TextBox> |
Les propriétés Text de TextBlock et TextBox sont des Dependancy Property, c'est à dire qu'elles implémentent INotifyPropertyChanged |
Pour accéder à un control qui n'est pas dans le fichier xaml, utiliser FindAncestor. |
Mode
Mode | |
---|---|
OneWay | Récupère une valeur de la Source pour modifier la Target |
OneWayToSource | Pousse une valeur de la Target pour modifier la Source |
TwoWay | Synchronisation |
OneTime | similaire à OneWay, mais ne met à jour l'UI qu'une seule fois à l'initialisation. |
Target: élément (graphique) contenant le Binding Source: élément ciblé par le binding (DataContext) |
TemplateBinding
Permet de créer une liaison entre le template et l'élément templaté.
<Button Content="Bouton"> <Button.Template> <ControlTemplate TargetType="{x:Type Button}"> <!-- liaison du Text de la TextBox avec le Content du Button --> <TextBlock Text="{TemplateBinding Content}"/> </ControlTemplate> </Button.Template> </Button> <Style BasedOn="{StaticResource {x:Type Button}}" TargetType="Button"> <Setter Property="Background" Value="Blue" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <!-- link the Background to the one defined in the style --> <TextBlock Background="{TemplateBinding Background}" /> </ControlTemplate> </Setter.Value> </Setter> </Style> |
TemplateBinding vs Binding TemplatedParent
Ce sont deux manières d'exprimer la même chose, mais Binding permet de modifier le Mode et l'UpdateSourceTrigger.
<TextBlock Text="{TemplateBinding Property=Content}"/> <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}"/> |
RelativeSource
<TextBlock Text="{TemplateBinding Property=Content}"/> <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}" /> <KeyBinding Key="Down" Command="{Binding Path=KeyboardCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Key}" /> |
Self
Créé un binding entre 2 propriétés du même control.
<Button Width="200" Height="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Width}">B1</Button> |
TemplatedParent
Créé un binding entre une propriété du template et une propriété du control contenant le template.
<Button Content="B3"> <Button.Template> <ControlTemplate TargetType="Button"> <Grid> <Ellipse Height="100" Width="150" Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}" /> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" /> </Grid> </ControlTemplate> </Button.Template> </Button> |
FindAncestor
Remonte l'arborescence d'éléments visuels WPF pour trouver un type de Control.
Il est possible de spécifier un AncestorLevel qui correspond au nième Control rencontré du type spécifié.
UserControl.xaml |
<UserControl x:Class="WpfApplication1.UserControl"> <StackPanel> <Button Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window, AncestorLevel=1}, Path=Background}">B2</Button> </StackPanel> </UserControl> |
Window.xaml |
<Window x:Class="WpfApplication1.MainWindow" xmlns:WpfApplication="clr-namespace:WpfApplication" Background="Pink"> <StackPanel> <WpfApplication:UserControl /> </StackPanel> </Window> |
Path=Children[1] permet d'accéder à la 2ème balise filles. 1 |
PreviousData
Permet de se binder avec l'élément précédent dans une ItemsSource.
Avec Values={1, 2, 3, 4, 5, 6, 7, 8, 9}, on a:
1 2 (Previous was 1) 3 (Previous was 2)
<ListBox ItemsSource="{Binding Path=Values}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding}" FontWeight="Bold" /> <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=PreviousData}, TargetNullValue='', StringFormat=' (Previous was {0})'}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> |
Source
Si la source du binding n'est pas spécifiée, c'est le DataContext qui est utilisé. Si celui-ci est null, c'est le premier DataContext non-null d'un parent qui sera utilisé.
<TextBlock Text="{Binding Source={StaticResource ResourceKey=MainVM}, Path=TextVM}"></TextBlock> |
Multibinding
<UserControl.Resources> <ResourceDictionary> <conversion:ArrayOfBooleansToVisibilityConverter x:Key="AllBooleanTrueToVisibilityConverter" /> <Button.Visibility> <MultiBinding Converter="{StaticResource AllBooleanTrueToVisibilityConverter}" FallbackValue="Collapsed"> <Binding Path="Prop1" /> <Binding Path="Prop2" /> </MultiBinding> |
ArrayOfBooleansToVisibilityConverter.cs |
[ValueConversion(typeof(bool[]), typeof(Visibility))] public class ArrayOfBooleansToVisibilityConverter : IMultiValueConverter { public bool IsInverted { get; set; } public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var result = values.All(v => object.Equals(v, true)); if (this.IsInverted) { result = !result; } return result ? Visibility.Visible : Visibility.Collapsed; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } |
StringFormat
<TextBlock Text="{Binding Name, StringFormat=Name: {0}}" /> <TextBlock Text="{Binding Date, ConverterCulture='fr-FR', StringFormat=Date: {0:D}}" /> |