Pregunta Guía de diseño de control de WPF - línea de tiempo


Estoy trabajando en un control para una de nuestras aplicaciones. El control muestra el día actualmente enfocado como un ceñidor, el eje X es la hora del día. El eje Y no tiene una escala como tal, sino que separará los elementos que se mostrarán. El aspecto general del control será bastante similar a un diagrama de Gantt, que muestra las horas del día de varias tareas. Para una idea (muy aproximada), vea el arte ascii (no) a continuación.

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

Tengo la cuadrícula de fondo elaborada para que se pueda redimensionar, y tiene un indicador de "hora actual" implementado como una línea azul vertical para mostrar dónde estamos en relación con las tareas. Cuando se cambia el tamaño del control, se recalcula la posición del indicador de tiempo actual para garantizar que muestre el tiempo correcto.

Lo que ahora no estoy seguro es cómo implementar las barras horizontales que representan los elementos de la tarea. Tengo una entidad de tarea con hora de inicio, hora de finalización, nombre y descripción y me gustaría que el control contenga una colección de estas entidades. También me gustaría que estas entidades manejen la pantalla.

Mi exposición a WPF es bastante limitada, pero en el pasado mis intentos de visualizar una colección de objetos han involucrado el uso de un cuadro de lista y placas de datos. Sería genial si fuera posible vincular una colección a un panel de pila o algo similar para que pudiera tener algo así. (Pensé en StackPabnel ya que manejaría el apilamiento vertical para mí)

<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>

¿Alguien puede decirme si lo que pensé aquí es incluso posible, y (con suerte) darme alguna orientación sobre cómo lograr lo que quiero hacer?

Gracias por adelantado.

--EDITAR--
El "control" que muestra cada tarea no tiene que ser algo más complicado que una línea con una hora de inicio y finalización, y una información sobre herramientas del nombre de la tarea. Por el momento, no necesito poder profundizar en las tareas, aunque esto puede ocurrir más tarde.


5
2017-12-07 14:15


origen


Respuestas:


Suponiendo que su clase de datos es algo como esto:

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

Puedes usar un ItemsControl Para disponer las entradas como rectángulos.

<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>

En el código XAML anterior, el panel del ItemsControl (que es la clase base ListBox, ListView, etc.) se cambia a una Canvas para un mejor posicionamiento de los artículos.

Puede usar ItemsControl.ItemTemplate para personalizar la forma en que se muestran los elementos.

He vinculado las propiedades de inicio e índice de la clase TimeLineEntry a Canvas.Left y Canvas.Top propiedades adjuntas de ItemContainer y también he utilizado convertidores de valor para convertir valores de DateTime en posiciones de píxeles.

El código para convertidores de valor es sencillo.

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();
    }
}

9
2017-12-07 20:10