WPF Советы по графическому отображению продолжительности включения / выключения последовательности - PullRequest
2 голосов
/ 04 января 2011

Я работаю над приложением, в котором пользователи могут выбирать между несколькими последовательностями продолжительности включения / выключения. Последовательности всегда начинаются с периода включения и могут иметь различную длину (но всегда в парах включения / выключения): например,

var sequences = new []
{
    new int[] { 10, 15 },        // 10 ms on, 15 ms off
    new int[] { 15, 10, 5, 10 }  // 15 ms on, 10 ms off, 5 ms on, 10 ms off
};

Последовательности имеют максимальную продолжительность 10 секунд и будут повторяться. Одна специальная последовательность не определяет длительности включения / выключения: она всегда включена (хотя я мог бы изменить ее на {1,0} или около того).

Вместо отображения чисел на экране я хотел бы показать небольшое графическое представление для полной 10-секундной продолжительности (повторяя более короткие последовательности), чтобы пользователь мог сравнивать шаблоны. Они будут отображаться в поле со списком, который изменяет размеры с окном. Для приведенных выше примеров это будет выглядеть примерно так (где X - закрашенный фон)

xx   xx   xx   xx   xx   xx   xx...
xxx  x  xxx  x  xxx  x  xxx  x  ...

Полагаю, мне придется использовать преобразователь значений (если только для специального значения), но я не уверен, каков наилучший / самый простой способ создания графиков, особенно с требованием изменения размера и повторением более коротких последовательностей. Холст, что-нибудь еще?

Буду очень признателен за любые советы!

1 Ответ

1 голос
/ 04 января 2011

Я бы следовал этому базовому подходу:

  1. Напишите преобразователь значений, который берет каждую последовательность и повторяет последовательность в полные 10 секунд, кодируя каждый фрагмент времени с помощью класса, который указывает, является ли период «Вкл.» И длительностью. *

  2. Для каждой последовательности свяжите с ItemSource элемента ItemsControl . Для ItemsPanel используйте StackPanel с горизонтальной ориентацией. Для ItemTemplate используйте Rectangle или любой другой визуал, который вы хотите в течение части времени, с шириной, привязанной к продолжительности. Вы также включили удобное свойство IsOn, чтобы вы могли легко визуализировать состояние «Вкл / Выкл». Не беспокойтесь о масштабировании ширины на этом этапе.

  3. Поместите ItemsControl в ViewBox , который может быть расширен до его родительского контейнера. Теперь у вас есть изображение, которое обеспечивает правильные пропорции продолжительности и масштабов с размером.


Вот простая реализация (без обработки ошибок или попыток сделать ее красивой):

UDPATE: исправлена ​​ошибка, из-за которой неправильно усекалась повторяющаяся последовательность в течение 10 секунд.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace TestWpf
{
    public class SeqSegment
    {
        public bool IsOn { get; set; }
        public int Duration { get; set; }
    }

    public class SeqConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var result = new List<SeqSegment>();
            var seq = (int[]) value;
            int time = 0;
            int i = 0;
            bool isOn = true;
            while (time < 10000)
            {
                result.Add(new SeqSegment { Duration = Math.Min(seq[i], 10000 - time), IsOn = isOn });
                isOn = !isOn;
                time += seq[i];
                i++;
                if (i >= seq.Length)
                    i = 0;
            }

            return result;
        }

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

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public IEnumerable<int[]> TestSequences
        {
            get
            {
                yield return new[] {10, 5000, 10, 8};
                yield return new[] {500, 5000};
                yield return new[] {50, 400, 30, 10};
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }
    }
}

XAML:

<Window x:Class="TestWpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:TestWpf="clr-namespace:TestWpf" Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <TestWpf:SeqConverter x:Key="SeqConverter"/>
        <DataTemplate x:Key="SeqSegTemplate">
            <Rectangle x:Name="Rect" Width="{Binding Duration}" Fill="Blue"/>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding IsOn}" Value="True">
                    <Setter TargetName="Rect" Property="Fill" Value="Green"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
        <DataTemplate x:Key="SeqTemplate">
            <Viewbox Height="50" Stretch="Fill">
                <ItemsControl ItemsSource="{Binding Converter={StaticResource SeqConverter}}" ItemTemplate="{StaticResource SeqSegTemplate}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal" Height="1"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </Viewbox>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ItemsControl ItemsSource="{Binding TestSequences}" ItemTemplate="{StaticResource SeqTemplate}"/>
    </Grid>
</Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...