2010-01-27 12 views
6

Poiché questo è WPF, può sembrare un sacco di codice, ma non spaventarti, la domanda è davvero semplice!WPF: impostazione di ItemSource in XAML e code-behind

Ho la seguente XAML:

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:hax="clr-namespace:hax" x:Class="hax.MainWindow" 
    x:Name="Window" Title="Haxalot" Width="640" Height="280"> 

    <Grid x:Name="LayoutRoot"> 
     <ListView ItemsSource="{Binding AllRoles}" Name="Hello"> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="Name" 
         DisplayMemberBinding="{Binding Path=FullName}"/> 
        <GridViewColumn Header="Role" 
         DisplayMemberBinding="{Binding Path=RoleDescription}"/> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Grid> 
</Window> 

ho questo code-behind:

using System.Collections.ObjectModel; 
using System.Windows; 

namespace hax 
{ 

    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 

     public ObservableCollection<Role> AllRoles { get { return m_AllRoles; } set { m_AllRoles = value; } } 
     private ObservableCollection<Role> m_AllRoles = new ObservableCollection<Role>(); 

     public MainWindow() 
     { 
      this.InitializeComponent(); 

      AllRoles.Add(new Role("John", "Manager")); 
      AllRoles.Add(new Role("Anne", "Trainee")); 
      // Hello.ItemsSource = AllRoles; // NOTE THIS ONE! 
     } 
    } 
} 

Se lascio la dichiarazione Hello.ItemSource = AllRoles commentata, la griglia visualizza nulla. Quando lo rimetto, mostra la cosa giusta. Perchè è questo?

risposta

15

questo:

<ListView ItemsSource="{Binding AllRoles}" Name="Hello"> 

significa "Bind ItemsSource alla proprietà this.DataContext.AllRoles" dove this è l'elemento corrente.

Hello.ItemsSource = AllRoles; 

significa "Bind ItemsSource a un ObservableCollection<T> piena di ruoli", che fa direttamente quello che stavi cercando di fare in origine.

Ci sono diversi modi per farlo in xaml. Eccone uno:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     this.InitializeComponent(); 
     var allRoles = new ObservableCollection<Role>() 
     allRoles.Add(new Role("John", "Manager")); 
     allRoles.Add(new Role("Anne", "Trainee")); 
     this.DataContext = allRoles; 
    } 
} 

e in XAML

<ListView ItemsSource="{Binding}" Name="Hello"> 

O, in alternativa, si potrebbe fare AllRoles una proprietà pubblica della finestra

public partial class MainWindow : Window 
{ 
    public ObservableCollection<Role> AllRoles {get;private set;} 
    public MainWindow() 
    { 
     this.InitializeComponent(); 
     var allRoles = new ObservableCollection<Role>() 
     allRoles.Add(new Role("John", "Manager")); 
     allRoles.Add(new Role("Anne", "Trainee")); 
     this.AllRoles = allRoles; 
    } 
} 

e quindi utilizzare un RelativeSource per dire al legame di salire sull'albero logico fino alla finestra

<ListView 
    ItemsSource="{Binding AllRoles, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 
    Name="Hello"> 

Che significa "Guarda i miei antenati finché non trovi una finestra, quindi cerca una proprietà pubblica nella finestra denominata AllRoles".

Ma il modo migliore per farlo è saltare il codice frigging del tutto e utilizzare il MVVM pattern. Ti suggerirei se stai imparando che salti direttamente al pattern MVVM. La curva di apprendimento è ripida, ma si impara tutto su binding e comandi e le cose importanti e interessanti su WPF.

0

Quando si esegue il binding a un'origine dati in WPF, è in cerca di una proprietà del contesto dati della finestra denominata "AllRoles". Controlla il modello Model-View-ViewModel per ulteriori informazioni sull'associazione dati in xaml. http://msdn.microsoft.com/en-us/magazine/dd419663.aspx