2009-09-09 8 views
1

J'essaie d'écrire un UserControl pour afficher une liste d'éléments où chacun de ces éléments est un titre et un groupe de cases à cocher. Cet ensemble représentera une forme de données où la personne qui remplit répond à une liste de questions avec une valeur de 1 à 4. Tout cela fonctionne et se lie bien au ViewModel de la fenêtre.WPF UserControl exposant des listitems internes

Mais j'ai actuellement obtenu les réponses codées en dur dans le UserControl comme suit:

<ListBox 
    ItemsPanel="{StaticResource HorizontalScores}" 
    Style="{StaticResource styleOuterListBox}" 
    ItemContainerStyle="{StaticResource styleOuterListBoxItem}"> 
    <ListBoxItem>Never</ListBoxItem> 
    <ListBoxItem>Sometimes</ListBoxItem> 
    <ListBoxItem>Often</ListBoxItem> 
    <ListBoxItem>Always</ListBoxItem> 
</ListBox> 

Je voudrais paramétrés de XAML ou de la ViewModel de la fenêtre, car ils seront différentes pour d'autres formes, mais peut Ne vois pas l'incantation correcte. Comment puis-je supprimer les ListBoxItems du contrôle UserControl et utiliser la liaison de données à la place?

BigEdit ...

Ok, cela est le contrôle de l'utilisateur réel (il semble hideux, mais ce n'est pas le point):

<UserControl x:Class="BussPerry.Scorer" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:BussPerry.ViewModel" xmlns:local="clr-namespace:BussPerry"> 

    <UserControl.Resources> 

    <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="Gray" /> 
    <SolidColorBrush x:Key="SelectedForegroundBrush" Color="Red" /> 

    <ItemsPanelTemplate x:Key="HorizontalScores"> 
     <StackPanel Orientation="Horizontal" /> 
    </ItemsPanelTemplate> 

    <Style x:Key="styleListBox" TargetType="{x:Type ListBox}"> 
     <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type ListBox}"> 
      <ItemsPresenter Margin="2" /> 
      </ControlTemplate> 
     </Setter.Value> 
     </Setter> 
    </Style> 

    <Style x:Key="styleListBoxItem" TargetType="{x:Type ListBoxItem}"> 
     <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
      <CheckBox Name="CheckBox" Padding="1" Width="60" 
          IsChecked="{Binding Path=IsSelected, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"> 
       <ContentPresenter HorizontalAlignment="Center"/> 
      </CheckBox> 
      <ControlTemplate.Triggers> 
       <Trigger Property="IsSelected" Value="True"> 
       <Setter TargetName="CheckBox" Property="Background" Value="{StaticResource SelectedBackgroundBrush}" /> 
       <Setter TargetName="CheckBox" Property="Foreground" Value="{StaticResource SelectedForegroundBrush}" /> 
       </Trigger> 
      </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
     </Setter> 
    </Style> 

    </UserControl.Resources> 

    <ListBox ItemsPanel="{StaticResource HorizontalScores}" Style="{StaticResource styleListBox}" 
     ItemContainerStyle="{StaticResource styleListBoxItem}" SelectedIndex="{Binding Path=Score}"> 
    <ListBoxItem>Never</ListBoxItem> 
    <ListBoxItem>Sometimes</ListBoxItem> 
    <ListBoxItem>Often</ListBoxItem> 
    <ListBoxItem>Always</ListBoxItem> 
    </ListBox> 

</UserControl> 

Et il est appelé comme suit:

<ListView 
    Name="listviewScores" 
    ItemsSource="{Binding Path=Scores}" 

    Margin="5" 
    BorderThickness="0" 
    Background="Transparent" 
    Focusable="False" 
    Grid.Row="3"> 
    <ListView.View> 
    <GridView 
     ColumnHeaderContainerStyle="{StaticResource styleHiddenHeader}"> 
     <GridView.Columns> 

     <GridViewColumn> 
      <GridViewColumn.CellTemplate> 
      <DataTemplate> 
       <TextBlock 
       Text="{Binding Path=Index}" 
       HorizontalAlignment="Right" /> 
       </DataTemplate> 
      </GridViewColumn.CellTemplate> 
     </GridViewColumn> 

     <GridViewColumn 
      DisplayMemberBinding="{Binding Path=Title}" /> 

     <GridViewColumn > 
      <GridViewColumn.CellTemplate> 
      <DataTemplate> 
       <local:Scorer > 
       </local:Scorer> 
      </DataTemplate> 
      </GridViewColumn.CellTemplate> 
     </GridViewColumn> 
     </GridView.Columns> 
    </GridView> 
    </ListView.View> 

</ListView> 

Ce que je veux faire est de déplacer les éléments de liste Jamais/Parfois/Souvent/Toujours d'être codé en dur dans le contrôle de l'utilisateur pour être databound.

(Suggestions de « vous ne voulez pas le faire comme ça » sont également les bienvenus!)

+0

J'ai lutté avec différentes techniques pour exposer les propriétés aux contrôles internes. La liaison de données fonctionne dans la plupart des scénarios, mais il semble y avoir quelques problèmes lors de l'utilisation de ce type de liaison de données à Collection d'éléments pouvant contenir des éléments ui. Dans ce cas, la liaison de données sur ces éléments semble être erronée. – jpierson

Répondre

0

Voulez-vous lier une collection à une zone de liste?

Il est assez simple ...

<ListBox ItemsSource="{Binding Answers}" /> 

où les réponses est votre collection exposée dans votre ViewModel.

Si vous rencontrez des problèmes lors de la création d'un contrôle personnalisé exposant ItemsSource, il vous suffit d'hériter de ItemsControl au lieu de UserControl.

EDIT: Quelques hypothèses:

  • DataContext du ListBox, contrôle personnalisé ou élément parent supérieur est fixé à votre ViewModel. Le ViewModel possède une propriété appelée "Réponses".
  • la propriété Answers implémente IEnumerable <>.
+0

Avec ceci, assurez-vous juste que vous définissez le DataContext de votre usercontrol. donc en XAML: Et YourData contient une propriété nommée Réponses comme SergioL disait plus haut. –

+1

@Mark - Oui, je suppose que cette connaissance ... aurait dû être explicite. – SergioL

+0

Je veux vraiment lier à deux collections, une à la liste montrant les lignes et l'autre à la liste affichant les colonnes. – amaca

1

(un an plus tard ...)

Je pense que votre question est semblable à la mienne. J'ai trouvé une technique pour exposer la ItemsSource d'un contrôle interne sur un UserControl. Le lien vers ma question est ici:

Exposing inner Control properties for binding in WPF

Je sais que ma solution fonctionne. Ce que je ne sais pas, c'est si cela viole certaines «meilleures pratiques» sacrées dans WPF. Cela semble juste.