2008-10-17 11 views
1

OK ... Je suis un gars de WinForms VB.NET essayant de comprendre WPF et tout son awesomeness. J'écris une application de base comme une expérience d'apprentissage, et j'ai lu beaucoup d'informations et regarder des vidéos de tutorat, mais je ne peux pas démarrer avec un simple DataBinding, et je sais qu'il me manque un concept de base. Autant que je l'aime, je n'ai pas eu ça "Aha!" moment de l'examen du code source pour le moment. Alors ... Dans ma classe Window j'ai défini une chaîne de propriétés personnalisée. Quand je vais dans Blend, j'essaye de créer une base de données avec le texte de ma TextBox sur cette propriété, mais ma propriété n'apparaît pas dans Blend comme quelque chose de disponible pour la liaison. Quelqu'un peut-il me dire ce que j'ai besoin d'ajouter à mon code/XAML ci-dessous ... et surtout pourquoi?Échec de la liaison de données - Aidez-moi à démarrer avec un exemple simple

Mon XAML:

<Window x:Class="Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <TextBox Text="How do I Bind my SomeText property here?"></TextBox> 
    </Grid> 
</Window> 

Mon code de fenêtre:

Class Window1 

    Private _sometext As String = "Hello World" 

    Public Property SomeText() As String 
     Get 
      Return _sometext 
     End Get 
     Set(ByVal value As String) 
      _sometext = value 
     End Set 
    End Property 

End Class 

Répondre

6

Voici comment vous devez changer votre XAML (le code est très bien).

<Window x:Class="Window1"  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
      Title="Window1" Height="300" Width="300" 
      DataContext="{Binding RelativeSource={RelativeSource Self}}">  
     <Grid>   
      <TextBox Text="{Binding SomeText}"> 
      </TextBox>  
     </Grid> 
    </Window> 

Pour comprendre les liaisons dans WPF, vous devez comprendre le DataContext. Chaque élément a une propriété DataContext et tout objet que vous placez dans cette propriété devient la source de données de toute liaison qui n'a pas de source de données explicite spécifiée. La valeur du DataContext est héritée d'un objet parent (dans ce cas, TextBox hérite du DataContext de la Grille, qui hérite du DataContext de Windows). Puisque vous voulez faire référence à une propriété de la fenêtre, vous devez définir le DataContext pour qu'il pointe vers l'occurrence de Window, ce que je fais dans l'attribut DataContext de la fenêtre.

Vous pouvez également modifier la source de données pour des liaisons individuelles en utilisant la syntaxe Source = ou RelativeSource = dans l'élément {Binding}.

+0

Merci, je vais essayer. Par conséquent, à propos de la chaîne de liaison "{Reliant RelativeSource = {RelativeSource Self}}" Est-ce que cela peut être généré dans Blend? Will VS m'aidera à le générer avec intellisense? Y a-t-il un moyen pour moi de découvrir la syntaxe correcte pour ces choses ou dois-je juste m'en souvenir? –

+0

Je ne pense pas Blend ou VS aide beaucoup dans ces cas. Si vous avez Resharper, cela ajoute un peu d'intellisense avec XAML. –

+0

Personnellement, j'aime mieux utiliser DataContext que d'utiliser ElementName (comme je l'ai fait dans ma réponse). J'ai seulement utilisé ElementName pour aider à clarifier ce qu'est la Source (à des fins d'apprentissage). DataContext apporte une complexité supplémentaire pour comprendre ...étant donné qu'il hérite de l'arbre visuel. – cplotts

5

Pour la liaison de données, il est utile de penser à plusieurs choses:

  1. Source objet
  2. objet cible (qui doit être un DependencyObject)
  3. Source de la propriété (la propriété sur l'objet source qui est participer à la liaison)
  4. propriété cible (qui doit être une propriété de dépendance)

Dans votre exemple de code:

  1. Source Object = Window1
  2. cible Object = TextBox
  3. Source Propriété = someText Propriété
  4. cible Propriété = Texte

L'extension de balisage de reliure va sur la Propriété target de l'objet Target.

Voici une photo qui illustre ce qui précède:

alt text

Vérifiez le code suivant (une façon de résoudre ce problème):

<Window 
    x:Class="WpfApplication2.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    x:Name="theWindow" 
    Title="Window1" 
    Height="300" 
    Width="300" 
> 
    <Grid> 
     <StackPanel> 
      <TextBox Text="{Binding ElementName=theWindow, Path=SomeText}"/> 
      <Button 
       Width="100" 
       Height="25" 
       Content="Change Text" 
       Click="Button_Click" 
      /> 
     </StackPanel> 
    </Grid> 
</Window> 

Dans l'extension de balisage Binding, je ont défini la source en utilisant ElementName ... ce qui vous permet d'utiliser un autre élément de votre arbre visuel comme source. Ce faisant, j'ai aussi dû donner un nom à la fenêtre avec l'attribut x: Name.

Il existe plusieurs façons de définir une source avec liaison (c'est-à-dire, Source, ElementName, DataContext) ... ElementName est juste un chemin. Une chose à noter est que la propriété Source ne doit pas être une propriété de dépendance, mais si ce n'est pas le cas, la propriété Target ne sera pas mise à jour ... sans aide spéciale. Jetez un coup d'œil sur le morceau de code suivant (excusez-moi, c'est C#, c'était plus rapide pour moi). Dans celui-ci vous me verrez implémenter INotifyPropertyChanged. Cela permet à un objet source de dire que quelque chose a changé ... et la liaison de données est assez intelligente pour le surveiller. Ainsi, si vous cliquez sur le bouton (à partir de l'exemple de code ici), il mettra à jour le TextBox. Sans implémenter cette interface (et si vous cliquez sur le bouton), le TextBox ne serait pas mis à jour.

J'espère que cela aide.

/// <summary> 
/// Interaction logic for Window1.xaml 
/// </summary> 
public partial class Window1 : Window, INotifyPropertyChanged 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
    } 

    private string _someText = "Hello World!"; 
    public string SomeText 
    { 
     get { return _someText; } 
     set 
     { 
      _someText = value; 
      OnNotifyPropertyChanged("SomeText"); 
     } 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnNotifyPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #endregion 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     this.SomeText = "Goodbye World!"; 
    } 
} 
1

WPF DataBinding est une fonctionnalité très puissante. Je vous suggère de lire quelques articles déjà existants sur le web, tels que

Très utile pour moi était aussi Beatrix Costa's blog on Data Binding.

+0

Je recommande également toutes les ressources ci-dessus. Le blog de Bea, en particulier, est remarquable sur ce sujet. – cplotts

0

La liaison de données avec une propriété CLR nécessite une étape supplémentaire. Vous devez implémenter INotifyPropertyChanged et déclencher l'événement PropertyChanged chaque fois que cette propriété CLR est modifiée. Cela ne le fera pas apparaître dans Blend, mais vous pouvez lier à la propriété en utilisant Text = "{Binding SomeText}" et en définissant le DataContext de la fenêtre à votre objet.

Il existe une alternative. Au lieu d'utiliser la liaison de données .NET, prenez en compte Update Controls .NET. C'est un projet open source qui remplace la liaison de données et ne nécessite pas INotifyPropertyChanged. Ce qu'il y a de formidable avec les contrôles de mise à jour, c'est qu'ils peuvent voir à travers la logique métier intermédiaire. Avec INotifyPropertyChanged, vous devez capturer et relancer les événements.

Questions connexes