2010-06-24 4 views
1

J'ai une listview que j'ai lié (twoWay) à une datatable. La liaison fonctionne correctement et les données s'affichent correctement dans la liste. Maintenant ce que je veux accomplir est un peu complexe et je ne suis même pas sûr que cela puisse être réalisé ou maintenant.DataBinding à un Listview

Mon datatable a dit 15 colonnes, et je montre 5 colonnes dans le lisview. Est-il possible que si l'utilisateur sélectionne une ligne sur listview, je pourrais afficher 10 autres valeurs pour cette ligne sélectionnée (à partir de la datatable) dans les blocs de texte dans stackpanel. Est-ce réalisable ou suis-je trop exigeant? J'ai essayé d'obtenir ceci en obtenant des idées de la question here, mais n'ai pas pu réaliser cela. Si c'est réalisable, pouvez-vous me donner des idées sur la façon de procéder?

Je pense que cela pourrait être réalisable en gérant l'événement listview1_selectionChanged et en remplissant les zones de texte manuellement, mais comme je suis dans une phase d'apprentissage, je voulais explorer si cela pouvait être fait par liaison de données. De cette façon, je vais connaître différentes façons de faire les choses et peut construire mes concepts dans le processus.

Je joins mon code ci-dessous. Ceci est juste un projet de test avec une listview ayant une colonne.

XAML:

<Window.Resources> 
    <Prefs:Tables x:Key="TClass"></Prefs:Tables> 
</Window.Resources> 
<Grid> 
    <StackPanel Orientation="Horizontal"> 
     <ListView Name="listView1" Background="Transparent" Height="534" BorderThickness="0 0 0 1" VerticalAlignment="Top"> 
      <ListView.ItemsSource> 
       <Binding Source="{StaticResource TClass}" Path="Instance.dtAccounts" Mode="TwoWay"></Binding> 
      </ListView.ItemsSource> 
      <ListView.View> 
       <GridView x:Name="GridView1" ColumnHeaderContainerStyle="{StaticResource GridViewHeader}" AllowsColumnReorder="True"> 
        <GridViewColumn Header="Company Name"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock x:Name="txbName" Padding="0 0 5 0" > 
            <TextBlock.Text> 
            <Binding Path="NAME"> 

            </Binding> 
             </TextBlock.Text> 
           </TextBlock> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
       </GridView> 
      </ListView.View> 
     </ListView> 
     <StackPanel Name="stkPanel1" Margin="100 0 0 0"> 
      <TextBlock></TextBlock> 
     </StackPanel> 
    </StackPanel> 
</Grid> 

Window1.xaml.cs

public partial class Window1 : Window 
{ 
    DataTable dt = new DataTable(); 
    public Window1() 
    { 
     InitializeComponent(); 
     Tables.Instance.dtAccounts = Worker.LoadAccounts(); 
    } 

} 

Classe Tables.cs

public class Tables : INotifyPropertyChanged 
{ 
    private static Tables instance; 
    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
    private DataTable _dtAccounts; 

    public Tables() 
    { 
    } 

    // Singleton instance read-only property 
    public static Tables Instance 
    { 
     get 
     { 
      if (instance == null) 
      { 
       instance = new Tables(); 
      } 
      return instance; 
     } 
    } 

    public DataTable dtAccounts 
    { 
     get 
     { 
      return _dtAccounts; 
     } 
     set 
     { 
      _dtAccounts = value; 
      OnPropertyChanged("dtAccounts"); 
     } 
    } 

    private void OnPropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 
    } 
} 

=====================

final Code du travail

j'ai pu le faire avec l'aide de réponse fournie par Phil. Publier mon code mis à jour ci-dessous, car il pourrait être utile pour quelqu'un d'autre.

XAML:

<Grid> 
    <StackPanel Orientation="Horizontal"> 
     <ListView Name="listView1" Background="Transparent" Height="534" BorderThickness="0 0 0 1" VerticalAlignment="Top" SelectionChanged="listView1_SelectionChanged"> 
      <ListView.ItemsSource> 
       <Binding Source="{StaticResource TClass}" Path="Instance.dtAccounts" Mode="TwoWay"></Binding> 
      </ListView.ItemsSource> 
      <ListView.View> 
       <GridView x:Name="GridView1" ColumnHeaderContainerStyle="{StaticResource GridViewHeader}" AllowsColumnReorder="True"> 
        <GridViewColumn Header="Company Name"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock Name="txbName" Padding="0 0 5 0" > 
            <TextBlock.Text> 
            <Binding Path="NAME"> 

            </Binding> 
             </TextBlock.Text> 
           </TextBlock> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
       </GridView> 
      </ListView.View> 
     </ListView> 
     <StackPanel Name="stkPanel1" Margin="100 0 0 0"> 
      <TextBlock> 
       <TextBlock.Text> 
        <Binding Source="{StaticResource TClass}" Path="Instance.SelectedName" Mode="TwoWay"> 

        </Binding> 
       </TextBlock.Text> 
      </TextBlock> 
     </StackPanel> 
    </StackPanel> 
</Grid> 

Window1.xaml.cs

public partial class Window1 : Window 
{ 
    DataTable dt = new DataTable(); 
    public Window1() 
    { 
     InitializeComponent(); 
     Tables.Instance.dtAccounts = Worker.LoadAccounts(); 
    } 

    private void listView1_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     ListView lstView = sender as ListView; 
     int item = lstView.SelectedIndex; 
     Tables.Instance.SetSelectedRow(item); 
    } 
} 

Tables.cs

public class Tables : INotifyPropertyChanged 
{ 
    private static Tables instance; 
    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
    private DataTable _dtAccounts; 
    private string _selectedName; 

    public Tables() 
    { 
    } 

    // Singleton instance read-only property 
    public static Tables Instance 
    { 
     get 
     { 
      if (instance == null) 
      { 
       instance = new Tables(); 
      } 
      return instance; 
     } 
    } 

    public DataTable dtAccounts 
    { 
     get 
     { 
      return _dtAccounts; 
     } 
     set 
     { 
      _dtAccounts = value; 
      OnPropertyChanged("dtAccounts"); 
     } 
    } 

    public string SelectedName 
    { 
     get 
     { 
      return _selectedName; 
     } 
     set 
     { 
      _selectedName = value; 
      OnPropertyChanged("SelectedName"); 
     } 

    } 

    public void SetSelectedRow(int index) 
    { 
     int indexNo = index; 
     SelectedName = dtAccounts.Rows[index][0].ToString(); 
    } 

    private void OnPropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 
    } 
} 

Répondre

1

Voici une base descripti d'une manière, vous pouvez y parvenir. Ce n'est pas une solution idéale, mais devrait vous mettre sur la bonne voie.

  1. Créez une variable de champ dans votre classe Tables qui représente une seule ligne dans votre datatable.
  2. Créez une méthode dans votre classe Tables qui définit cette variable de champ sur la ligne appropriée de votre table.
  3. Créez des propriétés qui exposent les valeurs de la ligne.
  4. La méthode de l'étape 2 devra faire une notification de modification pour toutes les propriétés exposées à l'étape 3 (OnPropertyChanged).
  5. Gérez l'événement selection_changed dans votre code et, depuis ce gestionnaire d'événements, appelez la méthode de votre classe Tables qui définit la ligne sélectionnée.
  6. Liez vos blocs de texte aux propriétés exposées à l'étape 3.
+0

Merci Phil, il a parfaitement fonctionné. Je vais coller le code mis à jour dans mon post original. Cela pourrait être utile à quelqu'un d'autre. –

1

Voici quelque chose comme ça:

public partial class DynamicListViewWindow : Window 
{ 
    public DynamicListViewWindow() 
    { 
     InitializeComponent(); 

     ObservableCollection<Person> personList = new ObservableCollection<Person>(); 

     personList.Add(new Person() { FirstName = "John", LastName = "Doe", Age = 30, Address = "123 Doe Street", Phone = "111-111-1111" }); 
     personList.Add(new Person() { FirstName = "Jane", LastName = "Doe", Age = 28, Address = "123 Doe Street", Phone = "222-222-2222" }); 
     personList.Add(new Person() { FirstName = "Mark", LastName = "Doe", Age = 15, Address = "123 Doe Street", Phone = "333-333-3333" }); 
     personList.Add(new Person() { FirstName = "John", LastName = "Smith", Age = 40, Address = "123 Doe Street", Phone = "444-444-4444" }); 
     personList.Add(new Person() { FirstName = "Rosy", LastName = "Smith", Age = 36, Address = "123 Doe Street", Phone = "555-555-5555" }); 

     PersonListView.ItemsSource = personList; 
    } 

    private void PersonListView_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (PersonListView.SelectedIndex >= 0) 
     { 
      Object data = PersonListView.SelectedItem; 
      PropertyInfo[] properties = data.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 

      ExtraPropertiesPanel.Children.Clear(); 

      foreach (PropertyInfo prop in properties) 
      { 
       TextBox tb = new TextBox(); 
       Binding b = new Binding() { Source = data, Path = new PropertyPath(prop.Name) }; 
       tb.SetBinding(TextBox.TextProperty, b); 
       ExtraPropertiesPanel.Children.Add(tb); 
      } 
     } 
    } 
} 

public class Person 
{ 
    public String FirstName { get; set; } 
    public String LastName { get; set; } 
    public Int32 Age { get; set; } 
    public String Address { get; set; } 
    public String Phone { get; set; } 
} 

XAML

<Window x:Class="WPFApplication1.DynamicListViewWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window" 
    Height="300" 
    Width="300"> 
<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 
    <Border Grid.Column="0"> 
     <ListView Name="PersonListView" SelectionChanged="PersonListView_SelectionChanged"> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="First Name" 
            DisplayMemberBinding="{Binding FirstName}" /> 
        <GridViewColumn Header="Last Name" 
            DisplayMemberBinding="{Binding LastName}" /> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Border> 
    <Border Grid.Column="1"> 
     <StackPanel Name="ExtraPropertiesPanel"></StackPanel> 
    </Border> 
</Grid>