Вопрос № 1
Параметр «Непрозрачность» в визуале, например «Граница», влияет на этот визуал и всех его потомков. Вот почему установка Border.Opacity заставляет все исчезать.
У вас есть два варианта: 1. Анимировать свойство border Stroke или 2. Изменить содержимое, чтобы оно не являлось потомком Border.
Анимация свойства Stroke тривиальна для кода, но имеет недостаток, заключающийся в том, что не все кисти легко поддаются анимации для прозрачных и обратно. Например, это сложно с градиентными кистями. Кроме того, если ваши границы были разными цветами и вы не хотели переходить на 100% прозрачность, нет хорошего способа анимировать обводку без изменения цвета.
Изменить контент, чтобы он не был потомком Border, очень просто, и я бы хотел сделать это в большинстве случаев. Просто замените:
<Border x:Name="MyBorder" Stroke="Red" StrokeThickness="3" CornerRadius="6">
<my:ContentHere />
</Border>
с этим:
<Grid>
<Border x:Name="MyBorder" Stroke="Red" StrokeThickness="3" Stroke="Red" CornerRadius="6">
<Border Stroke="Transparent" StrokeThickness="3" CornerRadius="Red">
<my:ContentHere />
</Border>
</Grid>
Теперь прозрачность видимой границы можно анимировать, а прозрачная - управлять макетом и обрезкой дочернего элемента.
Если у вас нет CornerRadius или другого забавного бизнеса, вы можете просто установить поле для содержимого и отказаться от прозрачной границы:
<Grid>
<Border x:Name="MyBorder" Stroke="Red" StrokeThickness="3" />
<my:ContentHere Margin="3" />
</Grid>
Вопрос № 2
На первый взгляд, я не вижу проблем с вашим XAML, из-за которых анимация будет продолжать работать после того, как значение срабатывания вернется к ложному значению, но я не очень внимательно посмотрел. Из того, что я заметил, я думаю, что это остановит анимацию при текущем значении, а не заставит ее работать.
Вы можете попробовать заменить StopStoryboard на RemoveStoryboard. RemoveStoryboard должен сбросить анимированные свойства обратно к их исходным значениям.