Silverlight: заставить Canvas аннулировать или перерисовать себя?

У меня есть приложение Silverlight, в котором есть Canvas. На этом холсте я динамически «рисую» кучу вещей, но добавляю элементы управления на холст.

У меня есть кнопка за пределами области холста, которая очищает содержимое. Объекты удалены (успешно). Однако область холста не обновляется сразу; в настоящее время для самого Canvas требуется событие MouseOver или другое событие.

Каков самый простой способ сделать внешний объект недействительным Canvas? Я уверен, что мне не хватает чего-то простого!


person pearcewg    schedule 30.01.2009    source источник


Ответы (4)


Это немного грязно, но вы можете попробовать изменить видимость на «Видимый» (хотя она уже есть) холста, поэтому:

myCanvas.Visibility = Visibility.Visible;

Мы обнаружили, что это приводит к перерисовке, даже если фактическое значение myCanvas.Visible не изменилось...

Попробуйте, это всего лишь один лайнер, который может все исправить. Хотя я ожидаю, что Canvas все равно будет перерисовываться, если вы удаляете из него что-то.

person George Sealy    schedule 01.02.2009
comment
Каким-то образом моя проблема решилась сама собой. Тем не менее, этот ответ отличный, потому что он очень мало влияет. Я, вероятно, добавлю это в свой код в качестве защитной меры. - person pearcewg; 02.02.2009

На случай, если кто-то придет после того, как я искал этот ответ...

yourFrameworkElement.InvalidateArrange();
yourFrameworkElement.UpdateLayout();

работал на меня.

Примечание: вызов только this.yourFrameworkElement.UpdateLayout(); у меня не работал. Мне пришлось позвонить InvalidateArrange(). Сразу после этого я позвонил UpdateLayout() для полноты информации - вероятно, это не имеет никакого реального влияния.

Также у меня не сработал трюк myCanvas.Visibility = Visibility.Visible;, поскольку я пытался вызвать событие LayoutUpdated.

person dFlat    schedule 20.09.2011
comment
Не вызвал перекраску для меня. Похоже, это не решение этой проблемы. - person Brett; 30.05.2012

Не простой однострочный, но он работает. Это хорошо работает в моем опыте. Он откладывает данное действие на десятую долю секунды, чтобы позволить потоку пользовательского интерфейса обновиться, но по-прежнему выполняет действие в потоке пользовательского интерфейса.

using System;
using System.Windows.Threading;

public static class MyTestClass
{
    public static void Postpone(Action a_action)
    {
        TaggedDispatchTimer timer = new TaggedDispatchTimer();
        timer.Interval = TimeSpan.FromSeconds(0.1);
        timer.Tick += OnDoPostponedAction;
        timer.UserState = a_action;
        timer.Start();
    }

    private static void OnDoPostponedAction(object sender, EventArgs e)
    {
        TaggedDispatchTimer timer = sender as TaggedDispatchTimer;
        timer.Stop();
        timer.Tick -= OnDoPostponedAction;

        var action = timer.UserState as Action;
        if (action != null)
            action();
    }
}

public class TaggedDispatchTimer : DispatcherTimer
{
    public Object UserState { get; set; }

}

Вот как я его использую:

MyTestClass.Postpone(() =>
    {
        // Do some bloody long operation.
    });
person Jordan    schedule 17.01.2012

В моем случае (у меня был холст внутри холста, и мне нужно было изменить размер внутреннего холста из-за изменения ориентации), трюк myCanvas.Visibility = Visibility.Visible; не помог, но он был очень близок:

myCanvas.Visibility = Visibility.Collapsed;
myCanvas.Visibility = Visibility.Visible;

работал просто отлично.

InvalidateArrange, за которым следует UpdateLayout, тоже не помогло.

В конце концов, все это было не нужно, так как я понял, что Canvas внутри Canvas не нужен и смог изменить внутренний Canvas на StackPanel, и никаких ухищрений не нужно, чтобы он работал как положено.

person Samo    schedule 17.05.2014