3

Le XAML ci-dessous est essentiellement en train de faire une liste des Button s (rendus de la propriété Name des objets dans leReliure à CurrentItem dans un ItemsControl

collection Views dans le DataContext courant. Lorsque je clique sur un bouton de la CurrentItem propriété de CollectionViewSource doit changer et l'associé View doit être affiché dans un présentateur contenu.

OK. Si je clique dans le ListBox dans le XAML dessous fonctionne exactement comme vous le souhaitez.

Mais, si je clique sur un bouton dans le UniformGrid (créé par le contrôle des éléments) la propriété CurrentItem n'est pas mise à jour.

Comment puis-je obtenir le CurrentItem à mettre à jour lorsqu'un élément est sélectionné dans le ItemsControl?

Merci

<UserControl x:Class="Pos.Features.Reservation.ReservationView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:product="clr-namespace:Pos.Features.ProductBrowser" 
      xmlns:activity="clr-namespace:Pos.Features.ActivityBrowser" 
      xmlns:addbysku="clr-namespace:Pos.Features.AddBySku" 
      xmlns:client="clr-namespace:Pos.Features.ClientBrowser" 
      xmlns:notes="clr-namespace:Pos.Features.Notes" 
      xmlns:controls="clr-namespace:Pos.Views" 
      xmlns:res="clr-namespace:Pos.Core;assembly=Pos.Core" 
      Height="300" Width="300"> 
    <UserControl.Resources> 
     <DataTemplate DataType="{x:Type product:ProductBrowserViewModel}"> 
      <product:ProductBrowserView/> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type activity:ActivityBrowserViewModel}"> 
      <activity:ActivityBrowserView/> 
     </DataTemplate> 

     <CollectionViewSource x:Name="x" x:Key="ViewsCollection" Source="{Binding Views}" /> 
    </UserControl.Resources> 

    <StackPanel> 
     <ListBox Name="ListBoxMenu" Grid.Column="0" Margin="5" ItemsSource="{Binding Source={StaticResource ViewsCollection}}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Name}" Padding="10"/> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
     <ContentControl Grid.Column="1" Content="{Binding ElementName=ListBoxMenu, Path=SelectedItem}"/> 
     <ItemsControl Grid.Column="2" Name="ViewList" ItemsSource="{Binding Source={StaticResource ViewsCollection}}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <Button> 
         <TextBlock Text="{Binding Path=Name}" Name="txtButtonLabel" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/> 
        </Button> 
       </DataTemplate>     
      </ItemsControl.ItemTemplate> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <UniformGrid Rows="1" Columns="{Binding Views.Count}"/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
     </ItemsControl> 
     <ContentControl Grid.Column="3" Content="{Binding Source={StaticResource ViewsCollection}, Path=CurrentItem}"/> 
     <Button Grid.Column="4" Click="Button_Click">dsadsd</Button> 
    </StackPanel> 
</UserControl> 

Répondre

11

Votre bouton ne fait rien. Habituellement, votre ViewModel aurait un ICommand appelé Select (ou quelque chose de similaire) que le bouton serait lié contre

Command="{Binding Select, ElementName="root"}"

et vous feriez passer l'instance à l'ICommand que vous souhaitez sélectionner

CommandParameter="{Binding}"

Il ressemblerait à quelque chose comme ça (C#/XAML comme pseudocode):

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

public class MyViewModel 
{ 
    public ObservableCollection<MyModel> Models {get;set;} 
    public ICommand Select {get;set;} 
    /* configure Models and Select etc */ 
} 

<UserControl DataContext="{StaticResource MyViewModelInstance}" x:Name="root"> 
<ItemsControl ItemsSource="{Binding Models}"> 
    <ItemsControl.ItemTemplate> 
    <ItemsPanelTemplate> 
     <Button Text="{Binding Name}" 
     Command="{Binding Select, ElementName="root"}" 
     CommandParameter="{Binding}"/> 
    </ItemsPanelTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 
</UserControl> 

Le ItemsControl se lie à modèles, de sorte que chaque MyModel dans modèles obtient un bouton. Le texte du bouton est lié à la propriété Nom. La commande de bouton est liée à la propriété Select dans ViewModel. Lorsque le bouton est pressé, il appelle l'ICommand, envoyant dans l'instance de MyModel que le bouton est lié.

S'il vous plaît faire noter que l'utilisation ViewModels dans un UserControl est une odeur de code . UserControl s devrait apparaître aux utilisateurs comme tous les autres contrôles - ils devraient avoir des propriétés publiques qui sont liées au ViewModel de l'utilisateur, pas le vôtre. Vous liez ensuite aux valeurs de ces propriétés dans le UserControl. Pour cet exemple, vous auriez une propriété ItemsSource définie sur votre UserControl, et le ItemsControl lierait directement à cette propriété plutôt qu'un ViewModel directement.

+0

Oui, c'est ce que je fais (en mon application n'est pas dans l'exemple), mais j'ai besoin de définir une propriété comme "IsActiveView" dans chaque modèle de vue et de synchroniser les autres modèles en définissant IsActiveView = false sur chacun d'entre eux. Il commence à neiger la balle. Le ListBox dans mon exemple fait ce dont j'ai besoin. N'existe-t-il pas un moyen de synchroniser un contrôle Items avec les éléments qu'il a créés? Le seul problème avec la zone de liste est qu'elle n'est pas horozontal et qu'elle ne fait pas de zones de taille uniforme. De toute façon, j'apprécie la pensée. Je vais attendre longtemps pour voir quelles autres idées surgissent. Merci – thrag

+0

C'est un peu difficile à saisir ce que vous essayez de faire dans votre application. Si je voulais montrer les détails d'un MyModel particulier, j'aurais une propriété publique MyModel Selected {get; set;} et je lierais un ContentControl. Vous pouvez avoir différents DataTemplates par type, donc quel que soit le type d'objet avec lequel vous vous liez sera montré en utilisant un DataTemplate différent ... – Will

+0

OK, cela fonctionne. Mais, une question suivante; si j'ai cinq boutons sur l'écran. Chacun active une vue liée à un contenu présent (comme vous le suggérez). Je veux avoir le bouton qui représente la vue active en surbrillance. Est-il possible d'utiliser un déclencheur pour modifier la couleur des boutons en fonction de la propriété de vue "Selected". Donc, un seul bouton est toujours coloré (mis en évidence comme actif.) Il se comporterait comme un contrôle de tabulation, mais je veux besoin des boutons espacés uniformément dans le haut. (Ce qui me fait penser que je devrais voir si je pourrais changer le template de l'onglet tab pour utiliser une grille uniforme – thrag

1

Je pense que vous devez le faire manuellement dans le code-behind.

XAML

<Button Click="ViewListButton_Click"> 
    <TextBlock Text="{Binding Path=Name}" Name="txtButtonLabel" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/> 
</Button> 

code-behind

private void ViewListButton_Click(object sender, RoutedEventArgs e) 
{ 
    Button button = sender as Button; 
    ICollectionView view = CollectionViewSource.GetDefaultView(ViewList.ItemsSource); 
    view.MoveCurrentTo(button.DataContext); 
} 

Si vous utilisez le modèle MVVM et/ou que vous ne souhaitez pas utiliser le code-behind, vous pourriez lier le Command du bouton à une commande dans votre ViewModel, comme suggéré par Will

Questions connexes