Ich habe vor einigen Tagen eine sehr nette Anwendung zum Betrachten von Fotos im Browser gesehen. Der Nachtteil bei der Anwendung war allerdings, das man vorher ein spezielles Plug-In (weder Flash noch Silverlight) installieren musste um sich das ganze zu Betrachten. Außerdem war es sehr groß … :(
Das geht leichter und einfacher und noch viel dynamischer dachte ich mir und habe deshalb mal ein eigenes Container-Control (ImageGrid) erstellt.
Schritt 1: Ableiten von der richtigen Klasse –> Panel
1: public class ImageGrid : Panel
2: {
3: protected override Size ArrangeOverride(Size finalSize)
4: {
5: double imageWidth = (double)this.GetValue(ImageWidthProperty);
6: double imageHeight = (double)this.GetValue(ImageHeightProperty);
7: int rowsPerColumn = (int)this.GetValue(RowsPerColumnProperty);
8: double imageMargin = (double)this.GetValue(ImageMarginProperty);
9:
10: int currentRow = 0;
11: int currentColumn = 0;
12:
13: foreach (Image image in this.Children.OfType<Image>())
14: {
15: Hover3DBehavior behavior = new Hover3DBehavior();
16: behavior.ZHoverValue = (double)this.GetValue(ZHoverValueProperty);
17: behavior.Attach(image);
18:
19: if ((bool)this.GetValue(ShowShadowProperty))
20: {
21: DropShadowEffect ds = new DropShadowEffect();
22: ds.Opacity = .3;
23: ds.BlurRadius = 10.0;
24: ds.Direction = 0.0;
25: ds.ShadowDepth = 20.0;
26: image.Effect = ds;
27: }
28:
29: Rect rect = new Rect(
30: currentColumn * (imageWidth + imageMargin),
31: currentRow * (imageHeight + imageMargin),
32: imageWidth,
33: imageHeight);
34:
35: image.Width = imageWidth;
36: image.Height = imageHeight;
37: image.Arrange(rect);
38: image.InvalidateArrange();
39:
40: currentRow++;
41: if (currentRow >= rowsPerColumn)
42: {
43: currentRow = 0;
44: currentColumn++;
45: }
46: }
47:
48: Size newSize = new Size((currentColumn+1) * (imageWidth + imageMargin), rowsPerColumn * (imageHeight+imageMargin));
49:
50: return base.ArrangeOverride(newSize);
51: }
52: }
Schritt 2: Erweitern mit netten Eigenschaften zum Konfigurieren
1: private const int C_DefaultRowsPerColumn = 5;
2: private const double C_DefaultImageWidth = 160.0;
3: private const double C_DefaultImageHeight = 120.0;
4: private const double C_DefaultZHover = 200.0;
5: private const bool C_DefaultShowShadow = true;
6: private const double C_DefaultImageMargin = 8.0;
7:
8: #region Images per column
10: public int RowsPerColumn
11: {
12: get { return (int)GetValue(RowsPerColumnProperty); }
13: set { SetValue(RowsPerColumnProperty, value); }
14: }
15:
16: public static readonly DependencyProperty RowsPerColumnProperty =
17: DependencyProperty.Register("RowsPerColumn", typeof(int),
18: typeof(ImageGrid),
19: new PropertyMetadata(C_DefaultRowsPerColumn,
20: new PropertyChangedCallback(OnImageSizeChanged)));
21:
22: #endregion
23:
24: #region Image Width
25:
26: public double ImageWidth
27: {
28: get { return (double)GetValue(ImageWidthProperty); }
29: set { SetValue(ImageWidthProperty, value); }
30: }
31:
32: public static readonly DependencyProperty ImageWidthProperty =
33: DependencyProperty.Register("ImageWidth", typeof(double),
34: typeof(ImageGrid),
35: new PropertyMetadata(C_DefaultImageWidth,
36: new PropertyChangedCallback(OnImageSizeChanged)));
37:
38: #endregion
40: #region Image Margin
41:
42: public double ImageMargin
43: {
44: get { return (double)GetValue(ImageMarginProperty); }
45: set { SetValue(ImageMarginProperty, value); }
48: public static readonly DependencyProperty ImageMarginProperty =
49: DependencyProperty.Register("ImageMargin", typeof(double),
50: typeof(ImageGrid),
51: new PropertyMetadata(C_DefaultImageMargin,
52: new PropertyChangedCallback(OnImageSizeChanged)));
53:
54: #endregion
55:
56: #region Image Height
57:
58: public double ImageHeight
59: {
60: get { return (double)GetValue(ImageHeightProperty); }
61: set { SetValue(ImageHeightProperty, value); }
62: }
63:
64: public static readonly DependencyProperty ImageHeightProperty =
65: DependencyProperty.Register("ImageHeight", typeof(double),
66: typeof(ImageGrid),
67: new PropertyMetadata(C_DefaultImageHeight,
68: new PropertyChangedCallback(OnImageSizeChanged)));
69:
70: protected static void OnImageSizeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
71: {
72: ImageGrid i = obj as ImageGrid;
73: i.InvalidateArrange();
74: }
75:
76: #endregion
77:
78: #region ZHoverValue
79:
80: public double ZHoverValue
81: {
82: get { return (double)GetValue(ZHoverValueProperty); }
83: set { SetValue(ZHoverValueProperty, value); }
84: }
85:
86: public static readonly DependencyProperty ZHoverValueProperty =
87: DependencyProperty.Register("ZHoverValue", typeof(double), typeof(ImageGrid),
88: new PropertyMetadata((double)C_DefaultZHover, null));
89:
90: #endregion
91:
92: #region Show Shadow
93:
94: public bool ShowShadow
95: {
96: get { return (bool)GetValue(ShowShadowProperty); }
97: set { SetValue(ShowShadowProperty, value); }
98: }
99:
100: public static readonly DependencyProperty ShowShadowProperty =
101: DependencyProperty.Register("ShowShadow", typeof(bool), typeof(ImageGrid),
102: new PropertyMetadata((bool)C_DefaultShowShadow, new PropertyChangedCallback(OnImageSizeChanged)));
103:
104: #endregion
Schritt 4: Erstellen eines Hover-Effektes mithilfe eines Behaviors
1: public class Hover3DBehavior : Behavior<UIElement>
3: PlaneProjection _planeProjection;
4:
5: public Hover3DBehavior()
6: : base()
7: {
8:
9: }
10:
11: Storyboard _hoverMe;
12: Storyboard _unhoverMe;
13:
14: private const double C_DefaultHoverValue = 500.0;
16: #region ZHoverValue
17:
18: public double ZHoverValue
19: {
20: get { return (double)GetValue(ZHoverValueProperty); }
21: set { SetValue(ZHoverValueProperty, value); }
22: }
24: public static readonly DependencyProperty ZHoverValueProperty =
25: DependencyProperty.Register("ZHoverValue", typeof(double), typeof(Hover3DBehavior),
26: new PropertyMetadata((double)C_DefaultHoverValue, null));
27:
28: #endregion
29:
30: #region Overrides
32: protected override void OnAttached()
33: {
34: base.OnAttached();
35:
36: _planeProjection = new PlaneProjection();
37: this.AssociatedObject.Projection = _planeProjection;
38:
39: if (!DesignerProperties.GetIsInDesignMode(this))
40: {
41: _hoverMe = new Storyboard();
42:
43: DoubleAnimation da1 = new DoubleAnimation();
44:
45: _hoverMe.Children.Add(da1);
46: da1.Duration = new Duration(new System.TimeSpan(0, 0, 0, 0, 300));
47: da1.To = this.ZHoverValue;
48: Storyboard.SetTarget(da1, this.AssociatedObject);
49: Storyboard.SetTargetProperty(da1, new PropertyPath("(UIElement.Projection).(PlaneProjection.LocalOffsetZ)"));
50:
51: DoubleAnimation da2 = new DoubleAnimation();
52: BounceEase be2 = new BounceEase();
53: be2.EasingMode = EasingMode.EaseOut;
54: be2.Bounces = 3;
55: da2.EasingFunction = be2;
56:
57: _unhoverMe = new Storyboard();
58: _unhoverMe.Children.Add(da2);
59: da2.Duration = new Duration(new System.TimeSpan(0, 0, 0, 0, 1000));
60: da2.To = 0.0;
61: Storyboard.SetTarget(da2, this.AssociatedObject);
62: Storyboard.SetTargetProperty(da2, new PropertyPath("(UIElement.Projection).(PlaneProjection.LocalOffsetZ)"));
64: if ((this.AssociatedObject as FrameworkElement).Resources.Contains("hoverme"))
65: {
66: (this.AssociatedObject as FrameworkElement).Resources.Remove("hoverme");
67: }
68: (this.AssociatedObject as FrameworkElement).Resources.Add("hoverme", _hoverMe);
70: if ((this.AssociatedObject as FrameworkElement).Resources.Contains("unhoverme"))
72: (this.AssociatedObject as FrameworkElement).Resources.Remove("unhoverme");
73: }
74: (this.AssociatedObject as FrameworkElement).Resources.Add("unhoverme", _unhoverMe);
75: }
76:
77: this.AssociatedObject.MouseEnter += new MouseEventHandler(AssociatedObject_MouseEnter);
78: this.AssociatedObject.MouseLeave += new MouseEventHandler(AssociatedObject_MouseLeave);
79: }
80:
81: protected override void OnDetaching()
82: {
83: base.OnDetaching();
84:
85: this.AssociatedObject.Projection = null;
86: _planeProjection = null;
87:
88: this.AssociatedObject.MouseEnter -= new MouseEventHandler(AssociatedObject_MouseEnter);
89: this.AssociatedObject.MouseLeave -= new MouseEventHandler(AssociatedObject_MouseLeave);
90: }
92: #endregion
94: #region Events
95:
96: void AssociatedObject_MouseLeave(object sender, MouseEventArgs e)
97: {
98: _unhoverMe.Begin();
99: }
100:
101: void AssociatedObject_MouseEnter(object sender, MouseEventArgs e)
102: {
103: _hoverMe.Begin();
104: }
105:
106: #endregion
107:
108: }
Schritt 3: Verwenden in Blend
Das ImageGrid nach dem ich einige Beispielbilder reingesetzt habe.
Der Arbeitsbereich
Der VisualTree.
Die zusätzlichen Konfigurationsmöglichkeiten.