2009-12-07 4 views
5

Je travaille sur un contrôle pour l'une de nos applications. Le contrôle montre le jour actuellement focalisé comme un cercle, l'axe des X étant l'heure du jour. L'axe Y n'a pas d'échelle en tant que telle, il va plutôt séparer les éléments à afficher. L'apparence générale du contrôle sera assez similaire à celle d'un diagramme de Gantt, montrant les heures de la journée de diverses tâches. Pour une idée (très approximative), voir l'ascii (pas) l'art ci-dessous.Guide de conception de contrôle WPF - chronologie

8  9  10  11  12  1  2  3  4  5  6 
----------------------------------------------------------------------------- 
|  |  |  |  |  |  |  |  |  |  | 
|  ======================  |  |  |  |  |  | 
|  |  |  ======================  |  |  |  | 
|  |  |  |  |  |  |  ========  |  | 
|  |  |  |  =========================================== 
|  |  |  |  |  |  |  |  |  |  | 

J'ai la grille de fond élaboré afin qu'il soit redimensionnable, et dispose d'un indicateur « heure » mis en œuvre par une ligne bleue verticale pour montrer où nous sommes en relation avec les tâches. Lorsque le contrôle est redimensionné, la position de l'indicateur de temps actuel est recalculée pour s'assurer qu'il affiche le bon moment. Ce dont je ne sais plus maintenant, c'est comment implémenter les barres horizontales qui représentent les éléments de la tâche. J'ai une entité de tâche avec l'heure de début, l'heure de fin, le nom et la description et j'aimerais que le contrôle contienne une collection de ces entités. J'aimerais aussi que ces entités conduisent l'affichage. Mon exposition à WPF est assez limitée, mais dans le passé, mes tentatives de visualisation d'une collection d'objets impliquaient l'utilisation d'une listbox et de datatemplates. Ce serait génial s'il était possible de lier une collection à un panneau de pile ou quelque chose de similaire, donc je pourrais avoir des semi-comme ça. (Je pensais StackPabnel car il traiterait empilement vertical pour moi)

<UserControl declarations here... > 
    <UserControl.Resources> 
     <ObjectDataProvider x:Key="myCollection" /> 
    </UserControl.Resources> 
    <Grid Name="myBackgroundGrid" Margin="0,0,0,0" ... >stuff goes here to draw the background</Grid> 
    <StackPanel ItemsSource="{Binding Source={StaticResource myCollection}}" /> 
</UserControl> 

Quelqu'un peut-il me dire si ce que je pensais d'ici est encore possible, et (espérons) me donner quelques conseils quant à la façon d'obtenir ce que je veux faire.

Merci d'avance. Le "contrôle" qui affiche chaque tâche ne doit pas être plus compliqué qu'une ligne avec une heure de début et de fin, et une info-bulle du nom de la tâche. Pour le moment, je n'ai pas besoin d'être capable d'effectuer des tâches, bien que cela puisse arriver plus tard.

Répondre

9

En supposant que votre classe de données est quelque chose comme ceci:

public class TimeLineEntry 
{ 
    public string Name { get; set; } 
    public DateTime Start { get; set; } 
    public int Index { get; set; } 
    public int Duration { get; set; } 
} 

Vous pouvez utiliser un ItemsControl pour exposer les entrées sous forme de rectangles.

<ItemsControl ItemsSource="{Binding}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Canvas IsItemsHost="True" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemContainerStyle> 
     <Style TargetType="{x:Type ContentPresenter}"> 
      <Setter Property="Canvas.Left" Value="{Binding Path=Start, Converter={StaticResource timeToPositionConverter}}" /> 
      <Setter Property="Canvas.Top" Value="{Binding Path=Index, Converter={StaticResource indexToPositionConverter}}" /> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate DataType="TimeLineEntry"> 
      <Rectangle Width="{Binding Duration}" Height="10" ToolTip="{Binding Name}" Fill="Red" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Dans le code XAML ci-dessus, le panneau de ItemsControl (qui est la zone de liste de classe de base, ListView, etc) est changé à un Canvas pour un meilleur positionnement des éléments.

Vous pouvez utiliser ItemsControl.ItemTemplate pour personnaliser la façon dont les éléments sont affichés. J'ai lié les propriétés Start et Index de la classe TimeLineEntry aux propriétés Canvas.Left et Canvas.Top attachées de ItemContainer et j'ai également utilisé des convertisseurs de valeurs pour convertir les valeurs DateTime en positions de pixels.

Les codes pour les convertisseurs de valeur sont simples.

public class IndexToPositionConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is int) 
     { 
      return ((int)value) * 10; 
     } 
     return 0; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
+0

Excellente réponse. Merci pour ça. Un peu de recherche et je fouund comment placer le IValueConverter dans le xaml avec dans ma section control.Resources. – ZombieSheep