Advertisement
Guest User

Untitled

a guest
Apr 26th, 2017
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.26 KB | None | 0 0
  1. public abstract class BaseSwitch : FrameworkElement {
  2. public static readonly DependencyProperty ResetElementNameBindingsProperty = DependencyProperty.Register(nameof(ResetElementNameBindings), typeof(bool),
  3. typeof(BaseSwitch), new FrameworkPropertyMetadata(false));
  4.  
  5. public bool ResetElementNameBindings {
  6. get { return (bool)GetValue(ResetElementNameBindingsProperty); }
  7. set { SetValue(ResetElementNameBindingsProperty, value); }
  8. }
  9.  
  10. protected abstract UIElement GetChild();
  11.  
  12. private UIElement _child;
  13.  
  14. private void SetActiveChild(UIElement child) {
  15. if (ReferenceEquals(_child, child)) return;
  16.  
  17. /* sometimes, different errors β€” such as β€œCannot modify the logical children
  18. for this node at this time because a tree walk is in progress.” β€” happen here */
  19.  
  20. RemoveVisualChild(_child);
  21. RemoveLogicalChild(_child);
  22.  
  23. _child = child;
  24.  
  25. AddLogicalChild(_child);
  26. AddVisualChild(_child);
  27.  
  28. if (ResetElementNameBindings) {
  29. child.ResetElementNameBindings();
  30. }
  31. }
  32.  
  33. protected override IEnumerator LogicalChildren => _child == null ? EmptyEnumerator.Instance :
  34. new SingleChildEnumerator(_child);
  35.  
  36. protected void UpdateActiveChild() {
  37. SetActiveChild(GetChild());
  38. }
  39.  
  40. protected static void OnChildDefiningPropertyChanged(object sender, DependencyPropertyChangedEventArgs e) {
  41. var b = sender as BaseSwitch;
  42. if (b == null) return;
  43.  
  44. b.UpdateActiveChild();
  45. b.InvalidateMeasure();
  46. b.InvalidateVisual();
  47. }
  48.  
  49. protected override Size MeasureOverride(Size constraint) {
  50. UpdateActiveChild();
  51.  
  52. var e = _child;
  53. if (e == null) return Size.Empty;
  54.  
  55. e.Measure(constraint);
  56. return e.DesiredSize;
  57. }
  58.  
  59. protected override Size ArrangeOverride(Size arrangeBounds) {
  60. _child?.Arrange(new Rect(arrangeBounds));
  61. return arrangeBounds;
  62. }
  63.  
  64. protected override int VisualChildrenCount => _child != null ? 1 : 0;
  65.  
  66. protected override Visual GetVisualChild(int index) {
  67. var child = _child;
  68. if (child == null || index != 0) throw new ArgumentOutOfRangeException(nameof(index));
  69. return child;
  70. }
  71.  
  72. protected static void OnWhenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
  73. var element = d as UIElement;
  74. if (element != null) {
  75. (VisualTreeHelper.GetParent(element) as BaseSwitch)?.UpdateActiveChild();
  76. }
  77. }
  78. }
  79.  
  80. internal class EmptyEnumerator : IEnumerator {
  81. private EmptyEnumerator() { }
  82.  
  83. public static IEnumerator Instance => _instance ?? (_instance = new EmptyEnumerator());
  84.  
  85. public void Reset() { }
  86.  
  87. public bool MoveNext() { return false; }
  88.  
  89. public object Current {
  90. get { throw new InvalidOperationException(); }
  91. }
  92.  
  93. private static IEnumerator _instance;
  94. }
  95.  
  96. internal class SingleChildEnumerator : IEnumerator {
  97. internal SingleChildEnumerator(object child) {
  98. _child = child;
  99. _count = child == null ? 0 : 1;
  100. }
  101.  
  102. object IEnumerator.Current => _index == 0 ? _child : null;
  103.  
  104. bool IEnumerator.MoveNext() {
  105. return ++_index < _count;
  106. }
  107.  
  108. void IEnumerator.Reset() {
  109. _index = -1;
  110. }
  111.  
  112. private int _index = -1;
  113. private readonly int _count;
  114. private readonly object _child;
  115. }
  116.  
  117. [ContentProperty(nameof(Children))]
  118. public abstract class ListSwitch : BaseSwitch, IAddChild, IList {
  119. protected readonly List<UIElement> UiElements = new List<UIElement>(2);
  120.  
  121. public IList Children => this;
  122.  
  123. public void CopyTo(Array array, int index) {
  124. ((IList)UiElements).CopyTo(array, index);
  125. }
  126.  
  127. public virtual int Count => UiElements.Count;
  128.  
  129. public object SyncRoot => ((IList)UiElements).SyncRoot;
  130.  
  131. public bool IsSynchronized => ((IList)UiElements).IsSynchronized;
  132.  
  133. public void RemoveAt(int index) {
  134. UiElements.RemoveAt(index);
  135. }
  136.  
  137. public UIElement this[int index] {
  138. get { return UiElements[index]; }
  139. set {
  140. var vc = UiElements;
  141. if (!ReferenceEquals(vc[index], value)) {
  142. vc[index] = value;
  143. InvalidateMeasure();
  144. }
  145. }
  146. }
  147.  
  148. public bool Contains(UIElement element) {
  149. return UiElements.Contains(element);
  150. }
  151.  
  152. public virtual void Clear() {
  153. UiElements.Clear();
  154. }
  155.  
  156. public int Add(UIElement element) {
  157. InvalidateMeasure();
  158.  
  159. UiElements.Add(element);
  160. return UiElements.Count;
  161. }
  162.  
  163. public int IndexOf(UIElement element) {
  164. return UiElements.IndexOf(element);
  165. }
  166.  
  167. public void Insert(int index, UIElement element) {
  168. InvalidateMeasure();
  169. UiElements.Insert(index, element);
  170. }
  171.  
  172. public void Remove(UIElement element) {
  173. UiElements.Remove(element);
  174. }
  175.  
  176. int IList.Add(object value) {
  177. return Add((UIElement)value);
  178. }
  179.  
  180. bool IList.Contains(object value) {
  181. return Contains(value as UIElement);
  182. }
  183.  
  184. int IList.IndexOf(object value) {
  185. return IndexOf(value as UIElement);
  186. }
  187.  
  188. void IList.Insert(int index, object value) {
  189. Insert(index, (UIElement)value);
  190. }
  191.  
  192. bool IList.IsFixedSize => false;
  193.  
  194. bool IList.IsReadOnly => false;
  195.  
  196. void IList.Remove(object value) {
  197. Remove(value as UIElement);
  198. }
  199.  
  200. object IList.this[int index] {
  201. get { return this[index]; }
  202. set { this[index] = (UIElement)value; }
  203. }
  204.  
  205. IEnumerator IEnumerable.GetEnumerator() {
  206. return UiElements.GetEnumerator();
  207. }
  208.  
  209. void IAddChild.AddChild(object value) {
  210. if (value == null) throw new ArgumentNullException(nameof(value));
  211.  
  212. var element = value as UIElement;
  213. if (element == null) throw new ArgumentException("Only UIElement supported", nameof(value));
  214.  
  215. Add(element);
  216. }
  217.  
  218. void IAddChild.AddText(string text) {
  219. if (!string.IsNullOrWhiteSpace(text)) throw new NotSupportedException();
  220. }
  221.  
  222. protected abstract bool TestChild(UIElement child);
  223.  
  224. protected override UIElement GetChild() {
  225. return UiElements?.FirstOrDefault(TestChild);
  226. }
  227. }
  228.  
  229. public class Switch : ListSwitch {
  230. public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(object),
  231. typeof(Switch), new FrameworkPropertyMetadata(null, OnChildDefiningPropertyChanged));
  232.  
  233. public object Value {
  234. get { return GetValue(ValueProperty); }
  235. set { SetValue(ValueProperty, value); }
  236. }
  237.  
  238. public static object GetWhen(DependencyObject obj) {
  239. return obj.GetValue(WhenProperty);
  240. }
  241.  
  242. public static void SetWhen(DependencyObject obj, object value) {
  243. obj.SetValue(WhenProperty, value);
  244. }
  245.  
  246. public static readonly DependencyProperty WhenProperty = DependencyProperty.RegisterAttached("When", typeof(object),
  247. typeof(Switch), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsParentMeasure, OnWhenChanged));
  248.  
  249. protected override bool TestChild(UIElement child) {
  250. return Value.XamlEquals(GetWhen(child));
  251. }
  252.  
  253. protected override UIElement GetChild() {
  254. return UiElements == null ? null : (UiElements.FirstOrDefault(TestChild) ??
  255. UiElements.FirstOrDefault(x => x.GetValue(WhenProperty) == null));
  256. }
  257. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement