One way to do this in a Generic and re-usable way is to use an OpacityMask with a VisualBrush and bind the values within the VisualBrush to the Image and the Grid. This way, it will work when the Image and Grid move around and change in Size etc. The VisualBrush can contain a Canvas and a Rectangle to achieve the 0.8 and 1.0 Opacity. Opacity can't be used on the Canvas however since it will effect the Opacity of the Rectangle so Background will do instead. 0.8 is equal to #CC000000. I used #50000000 to show the effect more clearly.

Update
Some workarounds were needed for the Silverlight version of this so I uploaded my sample app here: http://www.mediafire.com/?8pbj5b9t72m5191
WPF Version (Silverlight version will also work in WPF)
<Canvas x:Name="LayoutRoot" Background="White">
<Canvas.Resources>
<local:SubtractMultiConverter x:Key="SubtractMultiConverter"/>
<local:MaxValueMultiConverter x:Key="MaxValueMultiConverter"/>
</Canvas.Resources>
<Image Name="image" Source="C:\FG.png" Stretch="Fill" Height="300" Width="310" Canvas.Left="100" Canvas.Top="200">
<Image.OpacityMask>
<VisualBrush>
<VisualBrush.Visual>
<Canvas Background="#50000000"
Width="{Binding ElementName=image, Path=ActualWidth}"
Height="{Binding ElementName=image, Path=ActualHeight}">
<Rectangle Fill="#FF000000">
<Rectangle.Width>
<MultiBinding Converter="{StaticResource MaxValueMultiConverter}">
<Binding ElementName="rectToGetXAndY" Path="ActualWidth"/>
<Binding RelativeSource="{RelativeSource self}" Path="(Canvas.Left)"/>
<Binding ElementName="image" Path="ActualWidth"/>
</MultiBinding>
</Rectangle.Width>
<Rectangle.Height>
<MultiBinding Converter="{StaticResource MaxValueMultiConverter}">
<Binding ElementName="rectToGetXAndY" Path="ActualHeight"/>
<Binding RelativeSource="{RelativeSource self}" Path="(Canvas.Top)"/>
<Binding ElementName="image" Path="ActualHeight"/>
</MultiBinding>
</Rectangle.Height>
<Canvas.Left>
<MultiBinding Converter="{StaticResource SubtractMultiConverter}">
<Binding ElementName="rectToGetXAndY" Path="(Canvas.Left)"/>
<Binding ElementName="image" Path="(Canvas.Left)"/>
</MultiBinding>
</Canvas.Left>
<Canvas.Top>
<MultiBinding Converter="{StaticResource SubtractMultiConverter}">
<Binding ElementName="rectToGetXAndY" Path="(Canvas.Top)"/>
<Binding ElementName="image" Path="(Canvas.Top)"/>
</MultiBinding>
</Canvas.Top>
</Rectangle>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</Image.OpacityMask>
</Image>
<Grid x:Name="rectToGetXAndY" Canvas.ZIndex="3" Width="254" Height="143" Canvas.Left="123" Canvas.Top="272" Opacity="0.6"/>
</Canvas>
SubtractMultiConverter
public class SubtractMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double value = (double)values[0];
double subtractValue = (double)values[1];
return value - subtractValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
MaxValueMultiConverter
public class MaxValueMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double desiredWidth = (double)values[0];
double canvasValue = (double)values[1];
double actualWidth = (double)values[2];
return Math.Min(desiredWidth, actualWidth - canvasValue);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
Update
I noticed you wanted this to work in Silverlight as well. Silverlight doesn't have MultiBinding but fortuanetely Colin E. has a very nice solution for this.
VisualBrush is also missing, but Chris C. has a nice solution to that. I had to make some changes to VisualImage to make this work.
The changes were in OnVisualChanged, I added an EventHandler for LayoutUpdated and changed RenderSize to ActualWidth/ActualHeight
private FrameworkElement visual = null;
private void OnVisualChanged(DependencyPropertyChangedEventArgs args)
{
//if (args.OldValue != null) ((FrameworkElement)args.OldValue).SizeChanged -= VisualImage_SizeChanged;
if (args.NewValue != null)
{
visual = (FrameworkElement)args.NewValue;
visual.SizeChanged += VisualImage_SizeChanged;
visual.LayoutUpdated += new EventHandler(visual_LayoutUpdated);
PrepareBitmap((int)visual.ActualWidth, (int)visual.ActualHeight);
}
}
void visual_LayoutUpdated(object sender, EventArgs e)
{
PrepareBitmap((int)visual.ActualWidth, (int)visual.ActualHeight);
}
Silverlight Xaml
<UserControl.Resources>
<local:SubtractMultiConverter x:Key="SubtractMultiConverter"/>
<local:MaxValueMultiConverter x:Key="MaxValueMultiConverter"/>
<Canvas x:Key="testBorder"
Background="#50000000"
Width="{Binding ElementName=image, Path=ActualWidth}"
Height="{Binding ElementName=image, Path=ActualHeight}">
<Rectangle Fill="#FF000000">
<binding:BindingUtil.MultiBindings>
<binding:MultiBindings>
<binding:MultiBinding TargetProperty="Width"
Converter="{StaticResource MaxValueMultiConverter}">
<binding:MultiBinding.Bindings>
<binding:BindingCollection>
<Binding ElementName="rectToGetXAndY" Path="ActualWidth"/>
<Binding RelativeSource="{RelativeSource self}" Path="(Canvas.Left)"/>
<Binding ElementName="image" Path="ActualWidth"/>
</binding:BindingCollection>
</binding:MultiBinding.Bindings>
</binding:MultiBinding>
<binding:MultiBinding TargetProperty="Height"
Converter="{StaticResource MaxValueMultiConverter}">
<binding:MultiBinding.Bindings>
<binding:BindingCollection>
<Binding ElementName="rectToGetXAndY" Path="ActualHeight"/>
<Binding RelativeSource="{RelativeSource self}" Path="(Canvas.Top)"/>
<Binding ElementName="image" Path="ActualHeight"/>
</binding:BindingCollection>
</binding:MultiBinding.Bindings>
</binding:MultiBinding>
<binding:MultiBinding TargetProperty="Canvas.Left"
Converter="{StaticResource SubtractMultiConverter}">
<binding:MultiBinding.Bindings>
<binding:BindingCollection>
<Binding ElementName="rectToGetXAndY" Path="(Canvas.Left)"/>
<Binding ElementName="image" Path="(Canvas.Left)"/>
</binding:BindingCollection>
</binding:MultiBinding.Bindings>
</binding:MultiBinding>
<binding:MultiBinding TargetProperty="Canvas.Top"
Converter="{StaticResource SubtractMultiConverter}">
<binding:MultiBinding.Bindings>
<binding:BindingCollection>
<Binding ElementName="rectToGetXAndY" Path="(Canvas.Top)"/>
<Binding ElementName="image" Path="(Canvas.Top)"/>
</binding:BindingCollection>
</binding:MultiBinding.Bindings>
</binding:MultiBinding>
</binding:MultiBindings>
</binding:BindingUtil.MultiBindings>
</Rectangle>
</Canvas>
</UserControl.Resources>
<Canvas x:Name="LayoutRoot" Background="White">
<local:VisualImage x:Name="visualImage"
Visual="{Binding Source={StaticResource testBorder}}"
ImageBrush="{Binding ElementName=brush}"/>
<Image Name="image" Source="/GridImageOpacityMask;component/Images/FG.png" Stretch="Fill" Height="300" Width="310" Canvas.Left="200" Canvas.Top="200">
<Image.OpacityMask>
<ImageBrush x:Name="brush" />
</Image.OpacityMask>
</Image>
<Grid x:Name="rectToGetXAndY" Canvas.ZIndex="3" Width="254" Height="143" Opacity="0.6" Canvas.Left="223" Canvas.Top="272"/>
</Canvas>