Как изменить DrawingVisual Fill и Stroke

У меня есть объект DrawingVisual, и я хочу изменить его заливку и обводку.

Я пробовал это для заполнения:

DrawingVisual MyDrawing = new DrawingVisual();
SetFill(Brushes.Red, MyDrawing.Drawing);

Где SetFill:

private void SetFill(Brush fill, DrawingGroup group)
{
    foreach (Drawing drw in group.Children)
    {
        if (drw is DrawingGroup)
            SetFill(fill, drw as DrawingGroup);
        else if (drw is GeometryDrawing)
        {
            GeometryDrawing geo = drw as GeometryDrawing;
            geo.Brush = fill;

            using (DrawingContext context = MyDrawing.RenderOpen())
            {
                context.DrawDrawing(group);
            }
        }
    }
}

Но таким образом может случиться так, что мой DrawingVisual отрисовывается в другую позицию, как если бы преобразования не применялись больше (к MyDrawing).

Также, если я меняю эту инструкцию: context.DrawDrawing(group); на эту другую: context.DrawDrawing(MyDrawing.Drawing);, я получаю странный эффект: если я меняю Заливку в первый раз ничего не происходит, а во второй Заливка меняется правильно без изменения положения фигуры.

Как я могу сделать?


person gliderkite    schedule 09.05.2012    source источник
comment
Вы пытались просто установить GeometryDrawing.Brush рекурсивно, без перерисовки?   -  person Clemens    schedule 09.05.2012
comment
да, к сожалению, не влияет.   -  person gliderkite    schedule 09.05.2012
comment
Я боюсь, что ваше уродливое решение приведет к появлению все большего количества рисунков, потому что при каждом вызове SetFillEx вы помещаете существующую группу рисования в коллекцию Children новой группы рисования.   -  person Clemens    schedule 09.05.2012


Ответы (3)


Гораздо более простой подход к вашей проблеме (динамическое изменение заливки) заключается в использовании собственного SolidColorBrush для всех заливок и измените его Цвет при необходимости.

person Clemens    schedule 09.05.2012
comment
Вы имеете в виду SolidColorBrush для каждого DrawingVisual? Как я мог измениться таким образом? Не могли бы вы привести небольшой пример? Ps: вы видели мою правку? - person gliderkite; 09.05.2012
comment
В SetFill вы пытаетесь установить одну заливочную кисть для всех GeometryDrawings, чтобы все они имели одинаковый цвет заливки. Вместо этого вы могли бы использовать ровно одну кисть SolidColorBrush для всех этих рисунков, когда рисуете их в первый раз. Позже вам нужно только изменить эту SolidColorBrush, и цвет заливки всех рисунков изменится. - person Clemens; 09.05.2012
comment
Я не могу использовать это решение, потому что у меня сотни тысяч DrawingVisual, и я бы не хотел увеличивать рабочую нагрузку; см. мое последнее редактирование. - person gliderkite; 09.05.2012
comment
Какая нагрузка? Это всего лишь одна строка кода. Возможное недоразумение: я имею в виду не одну SolidColorBrush для каждого рисунка, а всего одну, одну для всех. Это так просто! - person Clemens; 09.05.2012
comment
Просто дайте мне посмотреть, как я могу использовать эту кисть, чтобы изменить заливку моего DrawingVisual, я думаю, что мы неправильно интерпретируем. - person gliderkite; 09.05.2012
comment
Только что увидел ваш новый вопрос. Как насчет ответа здесь, вы тем временем пробовали это? - person Clemens; 23.05.2012
comment
Да, вы были правы, когда говорили о моем уродливом решении. Я решил сохранить все кисти, потому что позже я узнал, что для других вещей мне нужно было делать это. У вас есть этот вопрос? - person gliderkite; 23.05.2012

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

private void SetFill(Brush fill, DrawingGroup group)
{
    foreach (Drawing drw in group.Children)
    {
        if (drw is DrawingGroup)
            SetFill(fill, drw as DrawingGroup);
        else if (drw is GeometryDrawing)
        {
            GeometryDrawing geo = drw as GeometryDrawing;
            geo.Brush = fill; // For changing FILL

            // We have to set Pen properties individually.
            // It does not work if we assign the whole "Pen" instance.
            geo.Pen.Brush = fill; 
            geo.Pen.Thickness = 1.0;
        }
    }
}
person Gags    schedule 20.05.2013

возможно, вы уже решили эту проблему, но вот мое решение, возможно, того же самого. У меня есть собственный DrawingVisual. Это свежий и не очень проверенный код, но пока он работает очень хорошо:

public class MyDrawingVisual : DrawingVisual
{
    private bool myIsSelected = false;

    public VillageInfo VillageInfo { get; set; }

    public bool IsSelected 
    {
        get { return myIsSelected; }
        set
        {
            if (myIsSelected != value)
            {
                myIsSelected = value;

                // Retrieve the DrawingContext in order to create new drawing content.
                DrawingContext drawingContext = this.RenderOpen();

                // Create a rectangle and draw it in the DrawingContext.
                Rect rect = new Rect(new System.Windows.Point(VillageInfo.X + 0.1, VillageInfo.Y + 0.1), new System.Windows.Size(0.9, 0.9));
                drawingContext.DrawRectangle(new SolidColorBrush(myIsSelected ? Colors.White : VillageInfo.Color), (System.Windows.Media.Pen)null, rect);

                // Persist the drawing content.
                drawingContext.Close();
            }
        }
    }
}
person absinth    schedule 20.08.2012