Одним из способов сделать это универсальным и многократно используемым способом является использование OpacityMask с VisualBrush и привязка значений в VisualBrush к изображению и сетке. Таким образом, он будет работать, когда изображение и сетка перемещаются и изменяют размер и т. Д. VisualBrush может содержать Canvas и Rectangle для достижения непрозрачности 0,8 и 1,0. Непрозрачность не может быть использована на холсте, однако, это повлияет на непрозрачность прямоугольника, так что фон будет делать вместо этого. 0.8 равно # CC000000. Я использовал # 50000000, чтобы показать эффект более четко.
Обновление
Для этой версии Silverlight потребовались некоторые обходные пути, поэтому я загрузил пример приложения здесь: http://www.mediafire.com/?8pbj5b9t72m5191
Версия WPF (версия Silverlight также будет работать в 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;
}
}
Обновление
Я заметил, что вы хотели, чтобы это работало и в Silverlight. Silverlight не имеет MultiBinding, но, к счастью, у Colin E. есть очень хорошее решение для этого .
VisualBrush также отсутствует, но у Криса С. есть хорошее решение для этого . Мне пришлось внести некоторые изменения в VisualImage, чтобы сделать эту работу.
Изменения были в OnVisualChanged, я добавил EventHandler для LayoutUpdated и изменил RenderSize на 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>