Рисование диаграммы в вопросах дизайна WPF C # - PullRequest
4 голосов
/ 28 июля 2011

Месяц назад у меня был проект, в котором я рисовал биржевую диаграмму в приложении с использованием Windows Forms. Я сделал это, создав растровое изображение, которое растянулось бы до размеров окна. Это позволило бы моему графику изменить размер вместе с окном.

Сейчас я расширяю проект с помощью WPF. Я пытался поработать над своим дизайном для проекта, но, похоже, я не могу понять, как лучше сделать тот же график. Я посмотрел на холсты, сетки и некоторые другие элементы управления. Я думал, что нахожусь на правильном пути с холстом, но когда я изменю размеры окна, мой рисунок останется на том же месте. Я предполагаю, что смысл моего сегодняшнего поста состоит в том, чтобы получить некоторые идеи, которые помогут мне придумать дизайн моего проекта.

Все советы и вопросы приветствуются.

Спасибо, Джозеф

Ответы [ 4 ]

1 голос
/ 09 марта 2015

(Реализация этого адреса в лучшем случае является подмножеством этого довольно старого вопроса, поскольку это только один тип диаграммы ...)

Просто попробуйте создать гистограмму в Grid как Edпредполагает довольно просто.Вот быстрая и грязная версия:

Добавьте Grid к XAML вашего Window.Просто для тестирования, вот тот, который полностью заполняет Window.

<Grid>
    <Grid
        Name="myGrid"
        HorizontalAlignment="Stretch"
        VerticalAlignment="Stretch"
        Width="auto"
        Height="auto"
        Margin="10,10,10,10"
    />
</Grid>

Теперь вставьте эти две служебные функции где-нибудь в вашем проекте.Они предоставляют простые одноцветные столбцы и не стилизованный, но центрированный текст метки для оси X.

Я думаю, что единственным неприятным ударом является maxHeight в вызове _placeSingleColorColumn.

Стоит упомянуть: У меня нет ярлыков для оси Y в этой быстрой и грязной версии.

private void _placeSingleColorColumn(Grid grid, Color color, int height, int colNum, int maxHeight)
{
    Brush brush = new SolidColorBrush(color);

    Rectangle rect = new Rectangle();
    rect.Fill = brush;
    Grid.SetColumn(rect, colNum);
    Grid.SetRow(rect, maxHeight - height);
    Grid.SetRowSpan(rect, height);

    grid.Children.Add(rect);
}

private void _createLabels(Grid grid, string[] labels)
{
    RowDefinition rowDefnLabels = new RowDefinition();
    grid.RowDefinitions.Add(rowDefnLabels);

    for (int i = 0; i < labels.Length; i++)
    {
        TextBlock block = new TextBlock();
        block.Text = labels[i];
        block.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
        Grid.SetColumn(block, i);
        Grid.SetRow(block, grid.RowDefinitions.Count);
        grid.Children.Add(block);
    }
}

Это действительно так.Вот несколько безумно быстрых и грязных примеров кода для создания сетки 10 на 10 с некоторыми примерами данных.

public void createGrid10x10()
{
    Random random = new Random();

    for (int i=0; i<10; i++)
    {
        ColumnDefinition colDef = new ColumnDefinition();
        myGrid.ColumnDefinitions.Add(colDef);

        RowDefinition rowDef = new RowDefinition();
        myGrid.RowDefinitions.Add(rowDef);

        Color color = i % 2 == 0 ? Colors.Red : Colors.Blue;

        _placeSingleColorColumn(this.myGrid, color, random.Next(1,11), i, 10);
    }
    string[] aLabels = "Dogs,Cats,Birds,Snakes,Rabbits,Hamsters,Horses,Rats,Bats,Unicorns".Split(',');
    _createLabels(this.myGrid, aLabels);
}

Добавьте одну строку в ваш MainWindow конструктор, и все готово, на самом деле.

public MainWindow()
{
    InitializeComponent();
    this.createGrid10x10();
}

Теперь у вас есть гистограмма, которая будет изменять размеры и оставаться пропорциональной при изменении размера окна и т. Д.

bar graph bar graph resized wider

Добавление дополнительных меток(значения столбцов сверху, метки оси Y и т. д.) должны быть довольно простыми, если вы понимаете вышесказанное.Просто добавьте другой столбец и / или строку, создайте TextBlock s и разместите их в нужных местах.

0 голосов
/ 28 июля 2011

Я предполагаю, что вы хотите нарисовать свой собственный график вместо использования графиков WPF.

Canvas, как правило, не рекомендуется использовать в WPF, поскольку он фиксирует объекты в определенном месте и размере, как вы уже видели (хотя я полагаю, что вы можете использовать Canvas с ScaleTransform). Сетка будет иметь размер своего контейнера, поэтому размещение сетки в окне приведет к изменению размера сетки вместе с окном (если вы не укажете фиксированную ширину и высоту для сетки). StackPanel будет складывать вещи и пытаться взять минимальный размер своего контента, так что это, вероятно, не то, что вы хотите использовать здесь.

Создание макета диаграммы внутри панели, такой как Grid, не совсем просто. Если вы делаете гистограмму, вы можете создать столбец в сетке для каждого столбца, назначить процентную ширину, например звездочку; и столбцы станут больше по мере того, как ваша Сетка расширяется вместе с окном. Вы можете использовать подобный прием, сделав каждый столбец сеткой, установив два столбца в сетке и установив третий уровень сетки внутри самого нижнего столбца, а затем используйте проценты для высоты столбцов (например, 90 звезд и 10 звезд для 90%, 10 % высоты). Стержни тогда становились выше, поскольку окно становилось выше. Вы можете зарезервировать строку сетки под полосами для меток и расположить их по центру под полосами.

Линейные графики сложнее. Возможно, вы захотите создать GeometryDrawing отрезков линии, а затем использовать ScaleTransform, привязанный к размеру окна, чтобы уменьшить и увеличить его.

Есть много возможностей с WPF, но сначала вам нужно немного наклониться и изучить. Книга Адама Натана "Windows Presentation Foundation Unleashed" быстро даст вам много знаний о макете WPF и о том, как действовать.

Редактировать: Вы также можете использовать пустую панель и использовать ее DrawingContext для рисования линий, прямоугольников, текста, эллипсов и т. Д. В точках, рассчитанных по текущему размеру окна.

0 голосов
/ 28 июля 2011

Забавно: я просто делаю то же самое!

Я уже разработал элемент управления диаграммой, множество функций. Теперь мне нужно обновить и расширить его с помощью другой функции. Тем не менее, моя задача состоит в том, чтобы управлять даже 100 тысячами точек на одном графике, но при этом сохранять хорошую производительность на обычном ПК. При изменении размера окна будет масштабироваться диаграмма, но не текст, в конечном итоге размещенный на нем. Также учтите, что мне нужно в реальном времени отрисовывать поступающие данные не менее 0,5 с.

Все, что было решено с использованием создания растрового изображения старого стиля, а затем размещения его как обычного изображения на любом элементе управления wpf. Есть несколько ограничений, потому что нет никаких «живых» объектов, как у wpf, но производительность рендеринга действительно огромна по сравнению с примитивами wpf.

Итак, если у вас нет диаграмм с максимум 100 точками, я настоятельно рекомендую гибридный подход. Во всяком случае, это очень сложная задача!

Приветствия

0 голосов
/ 28 июля 2011

Попробуйте использовать DockPanel и установите для LastChildFill значение true.Затем сделайте свой контроль последним дочерним элементом DockPanel .

...