Swiftmailer - еще один простой в использовании сценарий, который автоматически защищает от электронной почты и делает вложения легким. Я также настоятельно рекомендую использовать встроенную функцию mail()
PHP.
Чтобы использовать:
lib
в вашем проекте require_once 'lib/swift_required.php';
Теперь добавьте код, когда вам нужно отправить по электронной почте:
// Create the message
$message = Swift_Message::newInstance()
->setSubject('Your subject')
->setFrom(array('webmaster@mysite.com' => 'Web Master'))
->setTo(array('receiver@example.com'))
->setBody('Here is the message itself')
->attach(Swift_Attachment::fromPath('myPDF.pdf'));
//send the message
$mailer->send($message);
Более подробную информацию и параметры можно найти в Документах Swiftmailer .
WPF имеет встроенный механизм, который заставляет все Adorners
повторно измерять, переупорядочивать и повторно отображать каждый раз, когда соответствующий AdornedElement
изменяет размер, положение или преобразование. Этот механизм требует от вас соблюдения определенных правил при написании кода для украшения, не все из которых задокументированы так четко, как следовало бы.
Сначала я отвечу на ваш заглавный вопрос о , почему ваш рекламный щит не постоянно перерисовывается, а затем объясню, как это исправить.
Почему украшение не отображается повторно
Каждый раз, когда AdornerLayer получает уведомление LayoutChanged, он сканирует каждый из своих украшений, чтобы увидеть, не изменился ли AdornedElement
в размере, положении или преобразовании. Если это так, он устанавливает флаги, чтобы заставить Adorner
снова измерить, упорядочить и отрендерить - примерно эквивалентно InvalidateMeasure (); InvaliateArrange (); InvalidateVisual ();
.
В этой ситуации обычно происходит то, что элемент управления сначала измеряется, затем размещается, а затем визуализируется. Фактически, WPF пытается сделать это наиболее распространенным случаем, поскольку это наиболее эффективная последовательность. Однако есть много ситуаций, когда элемент управления может быть переупорядочен и / или повторно отрисован до того, как он будет повторно измерен. Это допустимый порядок событий в WPF (позволяющий использовать гибкие методы компоновки), но он встречается нечасто, поэтому часто не проверяется.
Правильно реализованный Adorner
или другой UIElement
будет осторожно вызывать InvalidateVisual ()
каждый раз, когда это может повлиять на рендеринг , кроме ] Свойства зависимости AffectsRender
были изменены.
В вашем случае размер вашего украшения явно влияет на рендеринг. Свойства размера не являются свойствами зависимости AffectsRender
, поэтому необходимо вручную вызывать InvalidateVisual ()
, когда они меняются. Если вы этого не сделаете, WPF, возможно, никогда не узнает, как заново отрисовать ваше украшение.
В вашей ситуации, вероятно, происходит следующее:
LayoutChanged
. AdornerLayer
обнаруживает изменение размера на вашем AdornedElement
AdornerLayer
планирует повторное измерение, изменение макета и повторную визуализацию вашего украшения. Arrange ()
, что приводит к повторному макету и повторному рендерингу до того, как повторно измерить. Это заставляет WPF думать, что украшение больше не нуждается в повторном макете или повторном рендеринге. Measure
MeasureOverride
повторно вычисляет желаемый размер , но ничего не делает, чтобы сообщить WPF, что рекламный элемент необходимо повторно отобразить. Что вы можете сделать, чтобы это исправить
Решение, конечно же, состоит в том, чтобы исправить ошибку в Adorner
, вызывая InvalidateVisual ()
каждый раз при повторном измерении элемента управления, например:
protected override Size MeasureOverride(Size constraint)
{
var result = base.MeasureOverride(constraint);
// ... add custom measure code here if desired ...
InvalidateVisual();
return result;
}
Выполнение этого заставит Adorner последовательно подчиняться всем правилам WPF, поэтому он будет работать как ожидается во всех ситуациях. Это также наиболее эффективное решение, поскольку InvalidateVisual ()
вообще ничего не будет делать, кроме тех случаев, когда это действительно необходимо.
Необходимо вызвать диспетчера на панели. Добавьте обработчик к событию TextBox SizeChanged:
private void myTextBox_SizeChanged(object sender, SizeChangedEventArgs e)
{
panel.Dispatcher.Invoke((Action)(() =>
{
if (panel.IsKeyboardFocusWithin)
{
// remove and add adorner to reset
myAdornerLayer.Remove(myAdorner);
myAdornerLayer.Add(myAdorner);
}
}), DispatcherPriority.Render, null);
}
Это в основном происходит из этого поста: http://geekswithblogs.net/NewThingsILearned/archive/2008/08/25/refresh--update-wpf-controls.aspx