Я создаю аналогичный эффект, который дает вам стекло AERO, размытое окно. Я быстро понял, что это непросто в WPF, но мне удалось заставить его работать почти полностью. Я просто застреваю, когда задействован Viewbox.Blur background with Viewbox
Так что я сделал это: я создал прямоугольник, сделал визуальную кисть, чтобы взять часть данного элемента фона, преобразовать окно просмотра, чтобы точно отобразить пространство изображения, которое прямоугольник перекрывает, и использовать его как заполнение для прямоугольника.
<Grid x:Name="grid">
<Image x:Name="image" Source="someImage.png"/>
<Rectangle x:Name="blurBackgroundRect" Width="100" Height="100">
<Rectangle.Effect>
<BlurEffect Radius="10"/>
</Rectangle.Effect>
<Rectangle.Fill>
<VisualBrush
ViewboxUnits="Absolute"
AlignmentX="Center"
AlignmentY="Center"
Visual="{Binding ElementName=image}"
Stretch="None">
<VisualBrush.Viewbox>
<MultiBinding Converter="{StaticResource visualBrushTargetConverter}">
<Binding ElementName="grid"/>
<Binding ElementName="blurBackgroundRect"/>
<Binding ElementName="grid" Path="ActualWidth"/>
<Binding ElementName="grid" Path="ActualHeight"/>
</MultiBinding>
</VisualBrush.Viewbox>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
Сетка ElementName, ссылается на общий родительский элемент моего прямоугольника и мое изображение. Я не могу сделать их предками, иначе это будет мешать эффекту размытия. Поэтому я размещаю их рядом друг с другом в сетке.
Заключительная часть - это многовалютный преобразователь, который выполняет фактические вычисления для окна просмотра VisualBrush.
public class VisualBrushTargetConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var parentControl = values[0] as FrameworkElement;
var targetControl = values[1] as FrameworkElement;
var transformedPos = targetControl.TransformToVisual(parentControl).Transform(new Point());
var transformedSize = targetControl.TransformToVisual(parentControl).Transform(new Point(targetControl.RenderSize.Width, targetControl.RenderSize.Height));
transformedSize = new Point(transformedSize.X - transformedPos.X, transformedSize.Y - transformedPos.Y);
return new Rect(transformedPos.X,
transformedPos.Y,
transformedSize.X,
transformedSize.Y);
}
}
Так что все это необходимо для воспроизведения моей следующей проблемы. Если вы хотите протестировать код, вы можете легко разместить его в простом приложении wpf.
Если вы проверите это, вы увидите, что он работает нормально. Проблема возникает, если мы поместим прямоугольник внутри окна просмотра и сетку с фиксированным размером (который имитирует мою фактическую проблему).
<Image x:Name="image" .../>
<Viewbox>
<Grid Width="800" Height="600">
<Rectangle x:Name="blurBackgroundRect" ...>
</Grid>
</Viewbox>
Так им угадать, что масштабирование от ViewBox применяется после Оформление печатных изданий, таким образом, не будут признаны в моих TransformTo звонков. Но я уже пытался использовать фактическое масштабирование Viewbox в моем конвертере, но не повезло. Пока Viewbox там, я не могу заставить его работать, поэтому я надеюсь, что у кого-нибудь есть идея, что может быть неправильно, или, может быть, даже указать мне на гораздо более простое решение. Я хочу, чтобы этот код впоследствии преобразовывался в пользовательский элемент управления, чтобы его легко использовать, поэтому я предпочитаю способы, которые не зависят от каких-либо особых условий.
+1 для хороших исследований и полного кода ... и для слова 'layouting' – Charleh