Here is how I made.
If you run the app, try resizing the window so that the clipped area will change accordingly to the rectangle's margin.
The right-side image should be always the same as the reddish covered area on the left.
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication5"
Title="MainWindow" Height="400" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid x:Name="grid1">
<Image
Source="http://icdn4.digitaltrends.com/image/microsoft_xp_bliss_desktop_image-650x0.jpg"
Stretch="UniformToFill"
x:Name="image1"
/>
<Rectangle
x:Name="control1"
Margin="50,10,100,80"
Fill="Red"
Opacity="0.33"
>
</Rectangle>
</Grid>
<Rectangle
Width="{Binding Path=ActualWidth, ElementName=control1}"
Height="{Binding Path=ActualHeight, ElementName=control1}"
Grid.Column="1"
>
<Rectangle.Fill>
<VisualBrush
Visual="{Binding ElementName=image1}"
ViewboxUnits="RelativeToBoundingBox"
>
<VisualBrush.Viewbox>
<MultiBinding>
<MultiBinding.Converter>
<local:MyConv />
</MultiBinding.Converter>
<Binding Path="ActualWidth" ElementName="grid1" />
<Binding Path="ActualHeight" ElementName="grid1" />
<Binding Path="Margin" ElementName="control1" />
</MultiBinding>
</VisualBrush.Viewbox>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Window>
You need also a converter:
public class MyConv : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var gw = (double)values[0];
var gh = (double)values[1];
var th = (Thickness)values[2];
var clip = new Rect(
th.Left / gw,
th.Top / gh,
(gw - th.Right - th.Left) / gw,
(gh - th.Bottom - th.Top) / gh
);
return clip;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Hope it helps.
Mario