Как рисовать на виджетах Canvas, встроенных в ListView - PullRequest
0 голосов
/ 05 декабря 2011

Это действительно основное требование, но я застрял! Для WPF / .Net - я просто хочу динамически рисовать в столбце Canvas в моем ListView. Одна неудачная попытка:

<ListView name="myGridView">
    <GridViewColumn Header="ColumnA" DisplayMemberBinding="{Binding Path=ColumnA}" />
    <GridViewColumn DisplayMemberBinding="{Binding Path=ColumnB}">
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SUSPECT!
        <Canvas Name="canvasColumn" Width="100" Height="20" />
    </GridViewColumn>
</GridView>

Внутри моего кода у меня есть класс "MyData" с полями, привязанными к столбцам ListView без холста. Я перебираю некоторые "Все, что создает" элементы в ListView:

foreach (Whatever whatever in whatevers)
{
    MyData myData = new MyData();
    myData.ColumnA = whatever.A;

    myData.ColumnB = new Canvas();
    Line line = new Line();
    line.Stroke = System.Windows.Media.Brushes.Black;
    line.X1 = line.Y1 = 1;
    line.X2 = line.Y2 = 100;
    line.StrokeThickness = 1;
    myData.ColumnB.Children.Add(line);

    myListView.Items.Add(myData);
}

Это НЕ РАБОТАЕТ: каждая строка в столбце экранного холста отображает текст «System.Windows.Controls.Canvas». Не страшно удивить - я связал столбец так же, как текстовые столбцы, и, кажется, вступает в силу некоторая конверсия типа toString. Но я попробовал несколько других вещей и просто не могу отобразить Canvas.

Я также попытался удалить привязку столбца, помеченную как "SUSPECT" выше, и поле myData ColumnB, пытаясь найти способ ссылки на виджеты Canvas через просмотр списка, то есть что-то в форме:

myListView.reference-to-new-row-and-canvas-column = theNewCanvasIDrewOn;

В результате некоторых моих поисков были обнаружены ужасные путаницы стилей, конфигов ItemPanel и т. Д.: Пожалуйста - если это необходимо, я, по крайней мере, надеюсь, что он может быть минимальным ....

Любое руководство с благодарностью.

Cheers, Tony

UPDATE

Для моих целей минимальным решением является добавление DataTemplate в тег Application.Resources App.xaml:

<DataTemplate x:Key="myTemplate">
    <Canvas Width="60" Height="20" Background="Red" ClipToBounds="True" >
        <ContentPresenter Content="{Binding myCanvasField}" />
    </Canvas>
</DataTemplate>

и определение GridViewColumn как:

<GridViewColumn CellTemplate="{StaticResource myTemplate}" Header="title" />

Спасибо Дину за то, что он указал мне правильное направление, и Привязка к холсту для деталей, специфичных для холста. Затем я «рисую» элемент свойства Canvas объекта, который добавляю в ListView.

Ответы [ 3 ]

1 голос
/ 05 декабря 2011

Вы можете использовать TaskVisualizer в качестве пользовательского элемента управления, а затем просто разместить его в своем шаблоне списка.Это отделяет ваш код визуализации задачи от вашего глобального кода пользовательского интерфейса.Преимущество этого заключается в том, что его легко повторно использовать в визуализации задачи, где, например, вы можете легко показать ту же графику во всплывающей подсказке при наведении курсора на задачу в каком-либо другом представлении.

1 голос
/ 05 декабря 2011

вам нужно использовать CellTemplate, а не Canvas напрямую

http://msdn.microsoft.com/en-us/library/system.windows.controls.gridviewcolumn.celltemplate.aspx

0 голосов
/ 05 декабря 2011

вот мое мнение.Идея состоит в том, чтобы использовать мини-DSL для обмена информацией между вашим холстом и бизнес-объектами.

XAML:

<Window x:Class="DrawInCanvas.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DrawInCanvas"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="g">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Id" Binding="{Binding Item1}" />
                <DataGridTemplateColumn Header="Bar">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Canvas HorizontalAlignment="Left" 
                                    Height="20"
                                local:CanvasDrawing.Drawing="{Binding Item2}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DrawInCanvas
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            // just a sample
            Dictionary<int, string> barDefinitions = new Dictionary<int, string>(3)
            {
                { 1, "100$red" },
                { 2, "220$yellow" },
                { 3, "40$blue" }
            };

            this.g.ItemsSource =
                Enumerable.Range(1, 3).Select(t => 
                    new Tuple<int, string>(t, barDefinitions[t]));
        }
    }

    public class CanvasDrawing : DependencyObject
    {
        public static readonly DependencyProperty DrawingProperty =
            DependencyProperty.RegisterAttached("Drawing",
                typeof(string),
                typeof(CanvasDrawing),
                new PropertyMetadata(new PropertyChangedCallback((o, e) => 
                {
                    CanvasDrawing.Draw((Canvas)o, (string)e.NewValue);
                })));

        public static void SetDrawing(Canvas canvas, string drawing)
        {
            canvas.SetValue(CanvasDrawing.DrawingProperty, drawing);
        }

        public static string GetDrawing(Canvas canvas)
        {
            return (string)canvas.GetValue(CanvasDrawing.DrawingProperty);
        }

        private static void Draw(Canvas canvas, string drawing)
        {
            string[] parts = drawing.Split("$".ToCharArray());

            canvas.Width = double.Parse(parts[0]);
            canvas.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString(parts[1]));
        }
    }
}
...