2017-03-01 1 views
0

Foreach treeview-item j'ai une propre grille de données. Treeview-items et dataagrids sont remplis par liaison.Comment obtenir l'objet SelectedItem de plusieurs datagrids?

Dans les zones de texte, j'ai une liaison à l'élément sélectionné des DataGrid. Mais la liaison sur ces zones de texte ne fonctionne qu'avec le premier DataGrid. Toutes les autres DataGrid ne transfère pas le SelectedItem aux champs de saisie:

wrong binding

Voici le treeview avec le DataGrid:

  <TreeView ItemsSource="{Binding Path=PlaceList}"> 
       <TreeView.ItemTemplate> 
        <DataTemplate> 
         <TreeViewItem Header="{Binding Path=Name}"> 
          <DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
             SelectionUnit="FullRow" 
             SelectedItem="{Binding SelectedMachine, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
             AutoGenerateColumns="True" 
             IsSynchronizedWithCurrentItem="True" 
             SelectionMode="Single"> 
          </DataGrid> 
         </TreeViewItem> 
        </DataTemplate> 
       </TreeView.ItemTemplate> 
      </TreeView> 

Voici la zone de texte:

<TextBox Text="{Binding PlaceList/SelectedMachine.Name, ValidatesOnDataErrors=True}" /> 

I travaille avec MvvmLight. Mon ViewModel détient le PlaceList:

public ObservableCollection<PlaceModel> PlaceList { get; set; } = new ObservableCollection<PlaceModel>(); 

    public ObjectInspectorViewModel() 
    { 
     PlaceList = PlaceModel.GetPlaces(BaseResourcePaths.PlacesCsv); 
    } 

C'est mon lieu-modèle:

public class PlaceModel 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } = "_CurrentObjectName"; 
    public string Length { get; set; } 
    public string Width { get; set; } 
    public string Height { get; set; } 
    public ObservableCollection<MachineModel> MachinesInPlace { get; set; } 
    public MachineModel SelectedMachine { get; set; } 

    public static ObservableCollection<PlaceModel> GetPlaces(string filepath) 
    { 
     [...] 
    } 
} 

j'ai essayé quelque chose, mais enfin je ne sais pas comment résoudre le bogue. Quel est le problème? Ma suggestion est la propriété '' SelectedMachine '' dans le lieu-modèle ...

Voici un exemple de projet (avec la solution supplémentaire de Sebastian Richter). Il montre les problèmes: https://www.file-upload.net/download-12370581/DatagridTreeViewError.zip.html

+0

N'avez-vous pas besoin d'un objet SelectedItem sur l'arborescence, puis faites vos liaisons dans les zones de texte basées sur cela?Sinon, les liaisons ne font que saisir la première instance et ne sont pas mises à jour lors de la sélection d'une arborescence. – Josh

+0

Merci pour votre réponse. J'ai essayé votre solution mais cela n'a pas fonctionné. J'ai dû étendre le contrôle treeview avec la propriété SelectedItem comme sur http://stackoverflow.com/a/3535089. Je me suis retrouvé avec le XAML suivant: http://pastebin.com/VVgBtCqR Le problème est que l'arborescence contient une liste pleine de place et dans chaque endroit est une liste différente (datagrid) des machines. Donc, sur treeview-select, je pourrais obtenir quelle place-liste est sélectionnée mais je ne pouvais pas obtenir quelle machine à l'intérieur de ces place-listes est sélectionné. Ou ai-je tort? – Chpo7234

Répondre

1

Je suis sûr que vous oubliez d'implémenter INotifyPropertyChanged dans votre classe PlaceModel. Le problème est qu'après avoir changé la sélection, la propriété Placemodel.SelectedMachine sera mise à jour mais aucun événement ne sera déclenché pour remplir cette modification dans la vue. Puisque vous utilisez MVVM Light, vous pouvez dériver de ObservableObject qui implémente déjà cette interface. changer donc votre PlaceModel au code suivant:

public class PlaceModel : ObservableObject 
{ 
    private MachineModel _selectedMachine; 
    public int Id { get; set; } 
    public string Name { get; set; } = "_CurrentObjectName"; 
    public string Length { get; set; } 
    public string Width { get; set; } 
    public string Height { get; set; } 
    public ObservableCollection<MachineModel> MachinesInPlace { get; set; } 

    public MachineModel SelectedMachine 
    { 
     get 
     { 
      return _selectedMachine; 
     } 

     set 
     { 
      // raises Event PropertyChanged after setting value 
      Set(ref _selectedMachine, value); 
     } 
    } 

    public static ObservableCollection<PlaceModel> GetPlaces(string filepath) 
    { 
    [...] 
} 

Edit:

Je suppose que la liaison ne sait pas quel élément de se lier à partir de votre ObservableCollection (plusieurs à un lien de parenté) parce que vous définissez comme référence dans votre TextBox.

essayer donc de retirer la SelectedMachine propriété du modèle et ajoutez-le à la ViewModel:

class ViewModel : ViewModelBase 
{ 
    ... 
    private MachineModel _selectedMachine; 
    public MachineModel SelectedMachine 
    { 
     get 
     { 
      return _selectedMachine; 
     } 
     set 
     { 
     // raises Event PropertyChanged after setting value 
     Set(ref _selectedMachine, value); 
     } 
    } 
    ... 
} 

aussi changer votre XAML au code suivant (je votre exemple de projet):

<Grid x:Name="LayoutRoot"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="2*"></RowDefinition> 
     <RowDefinition></RowDefinition> 
    </Grid.RowDefinitions> 

    <!-- Row #1 --> 
    <Grid> 
     <!-- TreeView und DataGrids--> 
     <TreeView ItemsSource="{Binding Path=PlaceList}"> 
      <TreeView.ItemTemplate> 
       <DataTemplate> 
        <TreeViewItem Header="{Binding Path=Name}"> 
         <DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
            SelectedItem="{Binding DataContext.SelectedMachine, RelativeSource={RelativeSource AncestorType=Window},Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
        </TreeViewItem> 
       </DataTemplate> 
      </TreeView.ItemTemplate> 
     </TreeView> 
    </Grid> 

    <!-- Row #2 --> 
    <Grid Grid.Row="1"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition></ColumnDefinition> 
      <ColumnDefinition Width="2*"></ColumnDefinition> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition></RowDefinition> 
      <RowDefinition></RowDefinition> 
     </Grid.RowDefinitions> 

     <Label Grid.Row="0" 
       Content="ID" /> 
     <!-- Textboxen aktualisieren nur bei Auswahl der ersten Datagrid --> 
     <TextBox Grid.Column="2" 
       Grid.Row="0" 
       Text="{Binding SelectedMachine.Id, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
     <Label Grid.Row="1" 
       Content="Name" /> 
     <TextBox Grid.Column="2" 
       Grid.Row="1" 
       Text="{Binding SelectedMachine.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
    </Grid> 
</Grid> 

La clé consistait à définir le DataContext correct pour SelectedItem. Pour cela, j'ai utilisé le code XAML suivant:

<DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
            SelectedItem="{Binding DataContext.SelectedMachine, RelativeSource={RelativeSource AncestorType=Window},Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 

Avec ceci votre exemple de projet met à jour les TextBox correctement.

+0

Merci pour votre aide. En effet j'ai oublié l'interface 'INotifyPropertyChanged' /' ObservableObject'. J'ai ajouté cette idée à mon code mais cela n'a pas résolu le problème. Dans ma question j'ai ajouté un exemple de projet qui montre le problème plus exactement. Je pense plutôt que 'SelectedMachine' doit être en dehors de' PlaceModel'. Mais si je mets les propriétés 'PlaceList' et' SelectedMachine' dans mon viewmodel, je ne peux pas accéder à 'SelectedMachine' dans mon xaml-datagrid, parce que je place un' PlaceList' dans l'arborescence ci-dessus: http://pastebin.com/ 20HwpPga – Chpo7234

+0

S'il vous plaît voir mon édition. –

+0

Je suis très reconnaissant pour vos efforts! Le studio visuellement problématique ne me montre pas la propriété 'DataContext.SelectedMachine' sur la fenêtre de liaison, donc je dois le configurer manuellement. Voir [cette image] (https://picload.org/image/rlcgogwr/binding2.png). Je n'aurais jamais pu trouver ça sans votre aide, merci beaucoup! – Chpo7234