[Silverlight入门系列]实现局部元素全屏(Element部分全屏)
本文不讨论Silverlight全屏模式的实现,有关实现这个,可以参考TerryLee的这篇文章,核心代码就是这行:
Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen;
本文要讨论的是Silverlight的局部元素全屏,即Element部分全屏。我们在做Silverlight项目中有时候客户有这种需求:希望放大界面的局部,比如一个列表面板啥的,而不是整个界面全屏。如下图:
实现部分全屏
实现起来也是比较简单,主要思路是用Popup实现弹出全屏,把需要全屏的元素放到容器里并设置为屏幕大小,然后整体实现全屏;当用户退出全屏的时候需要把元素恢复回原位置。好,我们写一个ElementsFullScreenProvider类,实现一个UIElement的扩展方法即可。
主要实现类:ElementsFullScreenProvider
1:
2: #region "Using Namespace"
3:
4: using System;
5: using System.Windows;
6: using System.Windows.Controls;
7: using System.Windows.Controls.Primitives;
8:
9: #endregion
10:
11: namespace ElementFullScreen
12: {
13: /// <summary>
14: /// Make partial UI elements full screen
15: /// Provider features:
16: /// make UI element full screen
17: /// exit full screen and restore UI element
18: /// support UIElement.ToggleElementFullScreen -- extension methods
19: /// </summary>
20: public static class ElementsFullScreenProvider
21: {
22: #region Members
23: static readonly Popup PopupContainer;
24: static readonly Panel PopupContentContainer;
25: static ElementController _lastElementController;
26: #endregion
27:
28: #region ElementController
29: class ElementController
30: {
31: double _height = double.NaN;
32: double _width = double.NaN;
33: int _lastPanelPosition;
34: bool _lastPopupIsOpen;
35: readonly DependencyObject _parent;
36: Thickness? _margin;
37:
38: public UIElement Element { get; private set; }
39:
40: public ElementController(UIElement element)
41: {
42: Element = element;
43:
44: var elem = element as FrameworkElement;
45: if (elem != null && elem.Parent != null)
46: {
47: _parent = elem.Parent;
48: }
49: }
50:
51: public void BringElementToFullScreen()
52: {
53: TryAction<FrameworkElement>(Element, f =>
54: {
55: _height = f.Height;
56: _width = f.Width;
57:
58: f.Height = double.NaN;
59: f.Width = double.NaN;
60: });
61:
62: TryAction<Control>(Element, f =>
63: {
64: _margin = f.Margin;
65:
66: f.Margin = new Thickness(0);
67: });
68:
69: if (_parent != null)
70: {
71: if (!TryAction<Panel>(_parent, p => { _lastPanelPosition = p.Children.IndexOf(Element); p.Children.RemoveAt(_lastPanelPosition); }))
72: if (!TryAction<ContentControl>(_parent, c => c.Content = null))
73: if (!TryAction<UserControl>(_parent, u => u.Content = null))
74: TryAction<Popup>(_parent, p => { _lastPopupIsOpen = p.IsOpen; p.Child = null; });
75: }
76: }
77:
78: public void ReturnElementFromFullScreen()
79: {
80: TryAction<FrameworkElement>(Element, f =>
81: {
82: f.Height = _height;
83: f.Width = _width;
84: });
85:
86: TryAction<Control>(Element, f =>
87: {
88: if (_margin.HasValue)
89: {
90: f.Margin = _margin.Value;
91: }
92: });
93:
94: if (_parent != null)
95: {
96: if (!TryAction<Panel>(_parent, p => p.Children.Insert(_lastPanelPosition, Element)))
97: if (!TryAction<ContentControl>(_parent, c => c.Content = Element))
98: if (!TryAction<UserControl>(_parent, u => u.Content = Element))
99: TryAction<Popup>(_parent, p => { p.Child = Element; p.IsOpen = _lastPopupIsOpen; });
100: }
101: }
102:
103: static bool TryAction<T>(object o, Action<T> action)
104: where T : class
105: {
106: T val = o as T;
107:
108: if (val != null)
109: {
110: action(val);
111: return true;
112: }
113:
114: return false;
115: }
116: }
117: #endregion
118:
119: #region FullscreenElementID Attached Property
120:
121: static readonly DependencyProperty FullscreenElementIDProperty = DependencyProperty.RegisterAttached(
122: "FullscreenElementID", typeof(Guid?), typeof(ElementsFullScreenProvider), new PropertyMetadata(null));
123:
124: static void SetFullscreenElementID(DependencyObject obj, Guid? value)
125: {
126: obj.SetValue(FullscreenElementIDProperty, value);
127: }
128:
129: static Guid? GetFullscreenElementID(DependencyObject obj)
130: {
131: return (Guid?)obj.GetValue(FullscreenElementIDProperty);
132: }
133: #endregion
134:
135: #region Initialization
136:
137: /// <summary>
138: /// Initializes the <see cref="ElementsFullScreenProvider"/> class.
139: /// </summary>
140: static ElementsFullScreenProvider()
141: {
142: PopupContentContainer = new Grid();
143:
144: PopupContainer = new Popup
145: {
146: Child = PopupContentContainer
147: };
148:
149: Application.Current.Host.Content.FullScreenChanged += delegate
150: {
151: if (_lastElementController == null) return;
152: if (!Application.Current.Host.Content.IsFullScreen)
153: {
154: ReturnElementFromFullScreen();
155: }
156: else
157: {
158: UpdateContentSize();
159: }
160: };
161: }
162: #endregion
163:
164: #region Public Methods
165:
166: public static void BringElementToFullScreen(this UIElement element)
167: {
168: if (_lastElementController == null)
169: {
170: _lastElementController = new ElementController(element);
171:
172: _lastElementController.BringElementToFullScreen();
173:
174: PopupContentContainer.Children.Add(element);
175: PopupContainer.IsOpen = true;
176: }
177: }
178:
179: public static void ReturnElementFromFullScreen(this UIElement element)
180: {
181: ReturnElementFromFullScreen();
182: }
183:
184: public static void ReturnElementFromFullScreen()
185: {
186: if (_lastElementController != null)
187: {
188: PopupContentContainer.Children.Clear();
189:
190: _lastElementController.ReturnElementFromFullScreen();
191:
192: PopupContainer.IsOpen = false;
193: _lastElementController = null;
194: }
195: }
196:
197: public static void ToggleElementFullScreen(this UIElement element)
198: {
199: bool newValue = !Application.Current.Host.Content.IsFullScreen;
200:
201: bool toggle = false;
202:
203: if (newValue)
204: {
205: if (_lastElementController == null)
206: {
207: element.BringElementToFullScreen();
208: toggle = true;
209: }
210: }
211: else
212: {
213: if (_lastElementController != null && ReferenceEquals(element, _lastElementController.Element))
214: {
215: element.ReturnElementFromFullScreen();
216: toggle = true;
217: }
218: }
219:
220: if (toggle)
221: {
222: ToggleFullScreen();
223: }
224: }
225:
226: public static void ToggleFullScreen()
227: {
228: Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen;
229: }
230:
231: #endregion
232:
233: #region Private Method
234:
235: private static void UpdateContentSize()
236: {
237: if (Application.Current != null && Application.Current.Host != null && Application.Current.Host.Content != null)
238: {
239: double height = Application.Current.Host.Content.ActualHeight;
240: double width = Application.Current.Host.Content.ActualWidth;
241:
242: //if (Application.Current.Host.Settings.EnableAutoZoom)
243: //{
244: // double zoomFactor = Application.Current.Host.Content.ZoomFactor;
245: // if (zoomFactor != 0.0)
246: // {
247: // height /= zoomFactor;
248: // width /= zoomFactor;
249: // }
250: //}
251:
252: PopupContentContainer.Height = height;
253: PopupContentContainer.Width = width;
254: }
255: }
256: #endregion
257: }
258: }
调用的时候使用UIElement的扩展方法实现全屏:
1: private void button1_Click(object sender, RoutedEventArgs e)
2: {
3: SilverArea/*你希望全屏的元素*/.ToggleElementFullScreen();//调用UIElement的扩展方法
4: }
源码下载
本文源码下载请点击此处。主要就一个类ElementsFullScreenProvider.cs,用起来就一个函数ToggleElementFullScreen(),简单之极。
推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架