画像の後ろに同じ画像が背景として見える感じの画像を表示する UserControl

#wpdev_jp #Win8dev_jp

タイトルではわけわからないですね。こういう感じの画像を作ってくれる UserControl です。

image

こんなものが必要か?

。。。画像を配置した時どうも殺風景だったり、さびしいとき。このコントロールを配置して画像を表示すれば、ちょっといい感じに。それほど大きくない画像もいい感じに見えます。こんな感じとか。

image

 

中身の解説

って、構造は見たままです。

  • 背景はGridで画像の表示と、メインの画像のレイアウト管理をになってます。
  • Rectangle の不透明度で暗さの調整をしています。
  • ドロップシャドウは今回はパスRectagle と Path オブジェクトで作り、Grid でまとめています。
  • 最後にメインのImageコントロールです。

image

設定用のプロパティは2つ

バインドがうまくいかなかったので、コードからプロパティの変化で直接書き換えてます。かっこ悪いー。

  • ImgSource は ImageSource 型:Grid の Background の ImageBrush の ImageSource と、中央の Image の ImageSource を書き換えます
  • BgDarkness は Double 型:0から100の値で、(100で割って)Rectangle の Opacity にしています。0から100にしたのは Blend で設定しやすいから

Grid は 3x3の9分割

このレイアウトの場合、Image の margin でレイアウトしてGrid の分割は使わない方法もあります。が、(3等分とか、比率でとか)画像の周りのスペースを自由にしながら管理したい場合は Grid を使ったほうがいいでしょう。

ということで、今回は Grid を分割して、縦、横、ともに 1:4:1 の割合で区切っています。なので、画像サイズが変わっても大体感じは一緒になります。結局UserControl のサイズによって中心の画像が決まる感じですね。

image

 

ドロップシャドウは自作

なにせ、APIとしてそういった機能がないので。画像を用意しようかと思ったのですが、解像度依存になったりするのと、ソースコードだけでやりたかったので自作です。単純に Rectangle と Path オブジェクト を作って並べているだけ。このために、もちろんGrid を9分割して配置に使っています。

imageimage

配置としては、親のGrid の中央に配置して、そこから 縦横 -20 はみ出して配置しています。ドロップシャドウだからね。周りのGrid に配置すると管理が面倒になるので。色は単純な線形のグラデーション。半透明の黒から透明へのグラデーションになっています。一応半透明の黒はリソースとして抽出して後から変更はできるようにしておいた。

追記

プロパティを追加して、ドロップシャドウの幅を調整できるようにした。上記のとおりMargin と、ドロップシャドウ用の Grid の上下左右の幅を変更してるだけ。枠のサイズに合わせてドロップシャドウのオブジェクトは勝手にサイズが変わります。ウマー。

 

作り方

プロジェクト>新しい項目の追加>ユーザーコントロール でユーザーコントロールを作ります。あとは、XAML 側にソースを流し込んで、C#のコードビハインド側にもプロパティを設定すれば完了です。

コンパイルすると、ツールボックスに作成したユーザーコントロールが現れますので、通常のコントロールのように配置します。

image

 

 

設定方法

プロパティは2つ。BgDarkness は 0から100の間で背景の暗さを指定します。元画像は imgSource でプロジェクトに追加した画像を指定します。

image

 

 

ソースコード

XAML側

 <UserControl x:Name="userControl"
       :
    d:DesignWidth="400" FontFamily="Global User Interface">
     
    <UserControl.Resources>
        <Color x:Key="ShadowColor">#7F000000</Color>
    </UserControl.Resources>

    <Grid x:Name="DropShadowPicture">
        <Grid.Background>
            <ImageBrush x:Name="img" Stretch="UniformToFill"/>

</Grid.Background>

<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="4*"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="4*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>

<Rectangle x:Name="brightness_dark"
Grid.ColumnSpan="3" Grid.RowSpan="3"
Fill="Black" Opacity="0.5" >
</Rectangle>

<Grid x:Name="dropshadow"
Grid.Column="1" Grid.Row="1" Margin="-20">

            <Grid.RowDefinitions>
                <RowDefinition x:Name="topshadow" Height="20"/>
                <RowDefinition/>
                <RowDefinition x:Name="bottomshadow" Height="20"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="leftshadow" Width="20"/>
                <ColumnDefinition/>
                <ColumnDefinition x:Name="rightshadow" Width="20"/>
            </Grid.ColumnDefinitions>

<Rectangle Grid.Column="1" Grid.Row="2">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Column="2" Grid.Row="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Path Data="M0,0 L128,128 L0,128 z" Stretch="Fill" Grid.Column="2" Grid.Row="2">
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path Data="M0,0 L128,0 L128,128 z" Stretch="Fill" Grid.Column="2" Grid.Row="2">
<Path.Fill>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Path.Fill>
</Path>

<Rectangle Grid.Column="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0,0.5" StartPoint="1,0.5">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Path Data="M0,0 L128,128 L0,128 z" Stretch="Fill" >
<Path.Fill>
<LinearGradientBrush EndPoint="0,0.5 " StartPoint="1,0.5">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path Data="M0,0 L128,0 L128,128 z" Stretch="Fill" >
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path Data="M128,0 L128,128 L0,128 z" Stretch="Fill" Grid.Row="2">
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path Data="M0,0 L128,0 L0,128 z" Stretch="Fill" Grid.Row="2">
<Path.Fill>
<LinearGradientBrush EndPoint="0,0.5" StartPoint="1,0.5">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path Data="M0,128 L128,128 L128,0 z" Stretch="Fill" Grid.Column="2" >
<Path.Fill>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path Data="M0,0 L128,0 L0,128 z" Stretch="Fill" Grid.Column="2" >
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="{StaticResource ShadowColor}"/>
<GradientStop Offset="0.7"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
</Grid>

        <Image x:Name="mainImage" Grid.Column="1" Grid.Row="1" 
               Stretch="UniformToFill"/>

</Grid>
</UserControl>

 

 

C#側

 public sealed partial class DropShadowImage : UserControl
{
     private int _shadowthickness =20;
    public int shadowthickness { get { return _shadowthickness;}
        set
        {
            _shadowthickness = value;
            dropshadow.Margin = new Thickness(-1 * value);
            topshadow.Height = new GridLength(value);
            bottomshadow.Height = new GridLength(value);
            leftshadow.Width = new GridLength(value);
            rightshadow.Width = new GridLength(value);
        }
    }

private ImageSource _imgSource;
public ImageSource imgSource
{
get { return _imgSource; }
set
{
if (value != null)
{
img.ImageSource = value;
mainImage.Source = value;
}
_imgSource = value;
}
}

private double _bgDarkness = 50;
public double BgDarkness
{
get { return _bgDarkness; }
set
{
if (value < 0) value = 0;
else if (value > 100) value = 100;
{
_bgDarkness = value;
brightness_dark.Opacity = value / 100;
}
}
}

     public DropShadowImage()
    {
        this.InitializeComponent();
    }
}

こうやってやれば いけそうなんだけど、どうもうまくいかない。UserControl だからかなのか?

<Rectangle Opacity =”{Binding Path=BgDarkness, RelativeSource={RelativeSource Mode=TemplatedParent} }”/>

追記

これでできた。できてしまえばシンプル。GUIでやる時は、ElementName から トップのuserControlを選んで、カスタムチェックをして Pathに直接 BgDarkness と入力する。

<Rectangle Opacity="{Binding BgDarkness, ElementName=userControl}" >