2009-09-17 7 views
0

Cela prend du temps. J'ajoute du code pour que vous puissiez voir ce que j'essaie de faire. Faites-moi savoir si quelque chose n'est pas clairLiaison de liste ListBox imbriquée WPF à l'aide de ViewModel

J'essaie d'obtenir des éléments sélectionnés de la liste déroulante imbriquée en mode multiselct. Voici le code (lot retiré de choses indésirables)

public class Item 
{ 
    public string Name { get; set; } 

    public IList<Item> SubItems { get; set; } // 

    public bool IsSelected { get; set; } 
} 
//Chicken Fried Chicken 
//A hearty boneless chicken breast, lightly breaded in our special seasonings and 
//golden fried. Served with garlic mashed potatoes, country gravy and seasonal vegetables 
// from Applebees 

//Item - Chicken Fried Chicken 
//SubItem- mashed potatoes 
//SubItem- country gravy 
//SubItem- seasonal vegetables 
//SubItem- Fries 
//SubItem- Sauted vegetables 
//SubItem- House Salad 

public class ItemViewModel : INotifyPropertyChanged, IItemViewModel 
{ 


    ObservableCollection<Item> selectedData = new ObservableCollection<Item>(); 

    private ObservableCollection<Item> todaysItems; 
    public ObservableCollection<Item> TodaysItems 
    { 
     get { return todaysItems; } 
     private set 
     { 
      if (todaysItems != value) 
      { 
       todaysItems = value; 
       PropertyChanged(this, new PropertyChangedEventArgs("todaysItems")); 
      } 
     } 
    } 



    public ItemViewModel(IItemView itemView) 
    { 
     this.View = itemView; 
     this.View.Model = this; 

     List<Item> items = service.GetAllTestItems(); 
     TodaysItems = new ObservableCollection<Item>(items); 

     selectedData.CollectionChanged += (sender, e) => UpdateSummary(); 
    } 



    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
    private void NotifyPropertyChanged(string propertyName) 
    { 
     var handler = this.PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 


    // How to get Selected Items from ListBox 

    public ObservableCollection<Item> SelectedData 
    { 
     get { return selectedData; } 
     set 
     { 
      selectedData = value; 
     } 
    } 


    private void UpdateSummary() 
    { 
     // here I can get selected data , I can find which Item is selected and then update its SubItems IsSelected (CLR) Property 
     // but something is not right here 
    } 
} 

XAML

<UserControl x:Class="ItemView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:prism="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation" 
      xmlns:ZCom="clr-namespace:MyProj.Infrastructure;assembly=Infrastructure"> 

    <Grid > 
     <ListBox ItemsSource="{Binding TodaysItems}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate > 
        <Border BorderThickness="1,1,1,1" CornerRadius="2,2,2,2" BorderBrush="Black"> 
         <Grid MinHeight="50" Width="150" Height="Auto" Margin="0,0,0,0"> 
          <Grid.RowDefinitions> 
           <RowDefinition /> 
           <RowDefinition/> 
           <RowDefinition /> 
          </Grid.RowDefinitions> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="150"/> 
           <ColumnDefinition Width="0"/> 
          </Grid.ColumnDefinitions> 
          <TextBlock Margin="4,4,2,2" Grid.Row="0" Width="Auto" TextWrapping="Wrap" Text="{Binding Path=Name}" /> 
          <Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" > 
           <Grid.Style> 
            <Style> 
             <Style.Triggers> 
              <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource= 
                    {RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}} 
              }" Value="false"> 
               <Setter Property="Grid.Visibility" Value="Collapsed"/> 
              </DataTrigger> 
             </Style.Triggers> 
            </Style> 
           </Grid.Style> 
           <Grid.RowDefinitions> 
            <RowDefinition Height="35"/> 
            <RowDefinition Height="*"/> 
           </Grid.RowDefinitions> 
           <TextBlock Margin="2,4,2,2" Grid.Row="0" Width="Auto" FontSize="10" FontStyle="Italic" TextWrapping="Wrap" Text="{Binding Path=Note}"/> 

           <ListBox Style="{DynamicResource MyStyle}" Grid.Row="1" ItemsSource="{Binding Path=Modifiers}" SelectionMode="Multiple" 
             ZCom:ListBoxHelper.SelectedItems="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.SelectedData}"> 
            <ListBox.ItemTemplate> 
             <DataTemplate > 
              <TextBlock Margin="2,2,2,2" TextWrapping="Wrap" Text="{Binding Path=Name}" /> 
             </DataTemplate> 

            </ListBox.ItemTemplate> 
           </ListBox> 
          </Grid> 

         </Grid> 
        </Border> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 
</UserControl> 

J'utilise ListBoxHelper (dans l'infrastructure) de http://marlongrech.wordpress.com/2009/06/02/sync-multi-select-listbox-with-viewmodel/

Je reçois la vue avec l'article et SubItems.

1) ce qui est mieux pour définir la propriété IsSelected de SubItems de ListBox imbriqué

Je vais ajouter une commande qui permet de stocker l'élément sélectionné à la base de données une fois double-cliqué. Les sous-éléments seront stockés en tant qu'enregistrement enfant en fonction de sa valeur IsSelected.

2) Existe-t-il un moyen de rendre observable la propriété SubItems de la classe C#? Je ne voudrais pas changer en ajoutant Observable à l'objet comme il sera dans un autre assemblage et peut être utilisé par d'autres applications.

Edit 1: question un peu utile trouvé

WPF Databinding to composite class patterns

Mais encore une fois pour cela, je vais devoir hériter de INotifyPropertyChanged.

Edit 2: Permettez-moi de voir si je peux expliquer ListBox1 mode de sélection est meilleur cours unique et parent & ListBox 2 est multiselect. ListBox1 est lié (source d'élément) à la propriété qui retourne observablecollection. ListBox2 est lié à une propriété dans la classe d'élément (Item.SubItems) qui renvoie IList. La classe d'élément a la propriété IsSelected. Je veux pouvoir sélectionner des sous-éléments qui devraient définir la propriété IsSelected pour les sous-éléments à true. Sachant qu'il n'y a pas d'héritage INotifyPropertyChanged dans la classe Item, comment puis-je y parvenir? Je suppose que, à moins que des sous-éléments ne tombent sous une collection observable, les changements ne seront pas notifiés à la source. En utilisant la propriété selectedData, je peux mettre à jour les sous-éléments en recherchant Item parent, mais ensuite mettre à jour la vue que je vais devoir firePropertChanged pour "items" qui implique tous les items et sous-items. Je veux que seuls les changements de sous-éléments soient notifiés par le mécanisme de liaison. Désolé si je ne suis toujours pas clair.

Edit 3:

Je pense qu'il n'y a aucun moyen de mettre en œuvre, mais INotifyPropertyChanged sur la classe d'objet. L'autre façon serait d'implémenter un modèle de vue qui est très spécifique aux besoins de vue mais cela ajoutera beaucoup de code.

Répondre

0

Il est un peu déroutant quel est votre objectif global ici.

Si vous essayez simplement d'obtenir les éléments sélectionnés à partir d'un ListBox imbriqué, avez-vous essayé de donner à votre ListBox un x:Name et d'exposer vos SelectedItems via une propriété de votre classe UserControl (ItemView)?

public IList SelectedItems 
{ 
    get { return nestedListBox.SelectedItems; } 
} 
+0

@ Guard- S'il vous plaît voir modifier 2. J'ai essayé de l'écrire comme commentaire mais il est devenu trop long – TheMar

Questions connexes