2010-01-27 4 views
6

Поскольку это WPF, это может выглядеть как много кода, но не пугайтесь, вопрос действительно прост!WPF: настройка ItemSource в XAML по сравнению с кодом

У меня есть следующий код 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> 

У меня есть этот код-за:

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

Если я оставлю заявление Hello.ItemSource = AllRoles закомментирована, сетка не отображает ничего. Когда я верну его обратно, он отображает правильную вещь. Почему это?

ответ

15

Это:

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

означает "Bind ItemsSource свойству this.DataContext.AllRoles", где this является текущий элемент.

Hello.ItemsSource = AllRoles; 

означает «Bind ItemsSource к ObservableCollection<T> полных ролей», которые непосредственно делает то, что вы пытаетесь сделать изначально.

Существует несколько способов сделать это в xaml. Вот один:

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

и в XAML

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

ИЛИ, альтернативно, вы могли бы сделать AllRoles открытое свойство окна

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

, а затем использовать RelativeSource к сообщите Binding, чтобы подойти к логическому дереву к окну

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

Это означает «Посмотрите на мою родословную, пока не найдете Окно, затем найдите общедоступное свойство в окне под названием AllRoles».

Но лучший способ сделать это - вообще пропустить кодовое шифрование и использовать MVVM pattern.. Я бы посоветовал, если вы узнаете, что переходите непосредственно к шаблону MVVM. Кривая обучения крутая, но вы узнаете все о привязке и командах и о важных, интересных вещах о WPF.

0

Когда вы привязываетесь к источнику данных в WPF, он ищет свойство контекста данных вашего окна под названием «AllRoles». Ознакомьтесь с шаблоном Model-View-ViewModel для получения дополнительной информации о привязке данных в xaml. http://msdn.microsoft.com/en-us/magazine/dd419663.aspx