Futurama - Bender's Big Score |
|
Очередная непонятка в WPF |
1 using System;
2 using System.Collections.Generic;
3 using System.Windows;
4 using System.Windows.Controls;
5 6 public class MyMenuItem: MenuItem
7 {8 private static MenuItem setHeader(MenuItem i, object h)
9 { 10 i.Header = h;11 return i;
12 } 13 14 private static List<Control> createItems()
15 {16 List<Control> list = new List<Control>();
17 list.Add(setHeader(new MenuItem(), "MenuItem 1"));
18 list.Add(new Separator());
19 list.Add(setHeader(new MenuItem(), "MenuItem 2"));
20 list.Add(new Separator());
21 list.Add(setHeader(new MyMenuItem(), "MyMenuItem"));
22 list.Add(new Separator());
23 list.Add(setHeader(new MenuItem(), "MenuItem 3"));
24 list.Add(new Separator());
25 list.Add(setHeader(new MenuItem(), "MenuItem 4"));
26 return list;
27 } 28 29 [STAThread]
30 public static void Main()
31 {32 Window w = new Window();
33 StackPanel sp = new StackPanel();
34 TextBlock tb = new TextBlock();
35 tb.Text = "Compare Separator before 'MyMenuItem' in MainMenu and ContextMenu...";
36 Menu m = new Menu();
37 sp.Children.Add(m); 38 sp.Children.Add(tb); 39 w.Content = sp;40 MenuItem mi = setHeader(new MenuItem(),"MainMenu");
41 mi.ItemsSource = createItems(); 42 m.Items.Add(mi); 43 44 ContextMenu cm = new ContextMenu();
45 cm.ItemsSource = createItems(); 46 w.ContextMenu = cm; 47 48 (new Application()).Run(w);
49 } 50 }
|
Грамотная реализация System.ComponentModel.INotifyPropertyChanged |
1 using System.Collections.Generic;
2 using System.ComponentModel;
3 using System.Reflection;
4 using System;
5 using PostSharp.Extensibility;
6 using PostSharp.Laos;
7 8 public class Demo1: INotifyPropertyChanged
9 {10 #region Вспомогательный код, может быть реализован в базовом классе
11 public event PropertyChangedEventHandler PropertyChanged;
12 protected void raisePropertyChanged(string propertyName)
13 {14 if(PropertyChanged!=null)
15 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
16 }17 protected void raisePropertyChanged(PropertyChangedEventArgs ea)
18 {19 if (PropertyChanged != null)
20 PropertyChanged(this, ea);
21 } 22 #endregion
23 24 private int myProperty;
25 26 /// <summary>
27 /// Классический метод
28 /// минусом является
29 /// 1) необходимость задавать имя свойство в виде строки
30 /// 2) создание нового экземпляра объекта PropertyChangedEventArgs
31 /// при каждом изменении свойства
32 /// </summary>
33 public int MyProperty
34 {35 get { return myProperty; }
36 set
37 {38 myProperty = value;
39 raisePropertyChanged("MyProperty");
40 } 41 } 42 43 44 private readonly PropertyChangedEventArgs myPropertyChangedEventArgs =
45 new PropertyChangedEventArgs("MyProperty2");
46 47 /// <summary>
48 /// Более красивый/правильный метод
49 /// к сожалению более громоздкий
50 /// к тому-же всё равно приходится
51 /// использовать строковую константу
52 /// </summary>
53 public int MyProperty2
54 {55 get { return myProperty; }
56 set
57 {58 myProperty = value;
59 raisePropertyChanged(myPropertyChangedEventArgs); 60 } 61 } 62 63 }64 public class Demo2 : INotifyPropertyChanged
65 {66 #region Вспомогательный код, может быть реализован в базовом классе
67 public event PropertyChangedEventHandler PropertyChanged;
68 private static Dictionary<string,PropertyChangedEventArgs> dictionary =
69 new Dictionary<string, PropertyChangedEventArgs>();
70 protected void raisePropertyChanged(string propertyName)
71 {72 if (PropertyChanged != null)
73 {74 PropertyChangedEventArgs value;
75 lock (dictionary)
76 {77 if(!dictionary.TryGetValue(propertyName, out value))
78 {79 value = new PropertyChangedEventArgs(propertyName);
80 dictionary.Add(propertyName, value); 81 } 82 }83 PropertyChanged(this, value);
84 } 85 }86 protected void raisePropertyChanged(MethodBase methodBase)
87 {88 // так как данный код вызывается из set-метода,
89 // имеющего наименование set_PropertyName
90 // поэтому просто выкусим первые 4 символа
91 raisePropertyChanged(methodBase.Name.Substring(4)); 92 } 93 #endregion
94 95 private int myProperty;
96 /// <summary>
97 /// Данный метод хорош тем что экономит память
98 /// (обходимся без выделения нового экземпляра PropertyChangedEventArgs)
99 /// к сожалению опять таки без использования текстовой константы не обошлось
100 /// </summary>
101 public int MyProperty
102 {103 get { return myProperty; }
104 set
105 {106 myProperty = value;
107 raisePropertyChanged("MyProperty");
108 } 109 }110 /// <summary>
111 /// Данный код позволил избавиться от использования
112 /// строковой константы. К сожалению даже для самых простых
113 /// и примитивных свойств нам все-таки приходится повторять
114 /// один и тот-же шаблон:
115 /// set
116 /// {
117 /// myProperty = value;
118 /// raisePropertyChanged(MethodBase.GetCurrentMethod());
119 /// }
120 /// </summary>
121 public int MyProperty2
122 {123 get { return myProperty; }
124 set
125 {126 myProperty = value;
127 raisePropertyChanged(MethodBase.GetCurrentMethod());
128 } 129 } 130 }131 /// <summary>
132 /// А теперь "нарисуем" базовый класс,
133 /// реализующий все возможности и преимущества
134 /// предыдущих методов и дополнительно
135 /// поддерживающий PostSharp
136 /// </summary>
137 public abstract class NotifyPropertyChangedBase: INotifyPropertyChanged
138 {139 public event PropertyChangedEventHandler PropertyChanged;
140 private static Dictionary<string, PropertyChangedEventArgs> dictionary =
141 new Dictionary<string, PropertyChangedEventArgs>();
142 protected void raisePropertyChanged(string propertyName)
143 {144 if (PropertyChanged != null)
145 {146 PropertyChangedEventArgs value;
147 lock (dictionary)
148 {149 if (!dictionary.TryGetValue(propertyName, out value))
150 {151 value = new PropertyChangedEventArgs(propertyName);
152 dictionary.Add(propertyName, value); 153 } 154 }155 PropertyChanged(this, value);
156 } 157 }158 protected void raisePropertyChanged(MethodBase methodBase)
159 {160 // так как данный код вызывается из set-метода,
161 // имеющего наименование set_PropertyName
162 // поэтому просто выкусим первые 4 символа
163 raisePropertyChanged(methodBase.Name.Substring(4)); 164 }165 protected void raisePropertyChanged(PropertyChangedEventArgs ea)
166 {167 if(PropertyChanged!=null) PropertyChanged(this, ea);
168 }169 /// <summary>
170 /// А вот этот метод сугубо для реализации через PostSharp
171 /// </summary>
172 /// <param name="propertyName">наименование свойства</param>
173 internal void internal_raisePropertyChanged(string propertyName)
174 { 175 raisePropertyChanged(propertyName); 176 } 177 }178 /// <summary>
179 /// Аттрибут для PostSharp-а
180 /// </summary>
181 [MulticastAttributeUsage(MulticastTargets.Property)]
182 [Serializable]
183 public sealed class NotifyThisPropertyChangedAttribute : CompoundAspect
184 {185 public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
186 {187 PropertyInfo pi = (PropertyInfo)element;
188 collection.AddAspect(pi.GetSetMethod(), new OnPropertySetSubAspect(pi.Name));
189 }190 /// <summary>
191 /// Проверка допустимости применения аспекта
192 /// </summary>
193 /// <param name="element">цель аспекта</param>
194 /// <returns>допустимость применения аспекта</returns>
195 public override bool CompileTimeValidate(object element)
196 {197 if (!base.CompileTimeValidate(element))
198 return false;
199 PropertyInfo pi = element as PropertyInfo;
200 if (pi == null)
201 return false;
202 if (!typeof(NotifyPropertyChangedBase).IsAssignableFrom(pi.DeclaringType))
203 return false;
204 if (!pi.CanWrite)
205 return false;
206 if (pi.GetSetMethod().IsStatic)
207 return false;
208 return true;
209 }210 /// <summary>
211 /// Implementation of <see cref="OnMethodBoundaryAspect"/> that raises the
212 /// <see cref="INotifyPropertyChanged.PropertyChanged"/> event when a property set
213 /// accessor completes successfully.
214 /// </summary>
215 [Serializable]
216 private class OnPropertySetSubAspect : OnMethodBoundaryAspect
217 {218 private readonly string propertyName;
219 /// <summary>
220 /// Initializes a new <see cref="OnPropertySetSubAspect"/>.
221 /// </summary>
222 /// <param name="propertyName">Name of the property to which this set accessor belong.</param>
223 public OnPropertySetSubAspect(string propertyName)
224 {225 this.propertyName = propertyName;
226 }227 /// <summary>
228 /// Executed when the set accessor successfully completes. Raises the
229 /// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.
230 /// </summary>
231 /// <param name="eventArgs">Event arguments with information about the
232 /// current execution context.</param>
233 public override void OnSuccess(MethodExecutionEventArgs eventArgs)
234 {235 NotifyPropertyChangedBase o = (NotifyPropertyChangedBase)eventArgs.Instance;
236 o.internal_raisePropertyChanged(propertyName); 237 } 238 } 239 } 240 241 /// <summary>
242 /// Демонстрируем "смешанное" использование
243 /// </summary>
244 public class PostSharpDemo1: NotifyPropertyChangedBase
245 {246 private int prop;
247 /// <summary>
248 /// Это свойство будет отслеживаться автоматически
249 /// </summary>
250 [NotifyThisPropertyChanged]
251 public int Prop{ get { return prop; } set { prop = value; } }
252 private string strProp;
253 /// <summary>
254 /// А здесь вызовем руками
255 /// </summary>
256 public string StrProp { get { return strProp; } set
257 {258 strProp = value;
259 raisePropertyChanged(MethodBase.GetCurrentMethod());
260 } 261 } 262 }
|
Сабж |
|
|
Упрощаем жизнь или PostSharp это наше фсё ;) |
1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using System.Windows;
5 using PostSharp.Extensibility;
6 using PostSharp.Laos;
7 8 namespace PostSharpDemo
9 {10 /// <summary>
11 /// Классическая реализация 2-х свойств
12 /// </summary>
13 public class ClassicImplementation: DependencyObject
14 {15 public static readonly DependencyProperty DemoStringProperty =
16 DependencyProperty.Register(
17 "DemoString",
18 typeof (string), typeof (ClassicImplementation),
19 new PropertyMetadata("Default String Value"));
20 public static readonly DependencyProperty DemoInt32Property =
21 DependencyProperty.Register(
22 "DemoInt32",
23 typeof(string), typeof(ClassicImplementation),
24 new PropertyMetadata(0));
25 26 public int DemoInt32
27 {28 get { return (int) GetValue(DemoInt32Property); }
29 set { SetValue(DemoInt32Property, value); }
30 } 31 32 public string DemoString
33 {34 get { return (string)GetValue(DemoStringProperty); }
35 set { SetValue(DemoStringProperty, value); }
36 } 37 } 38 39 /// <summary>
40 /// А вот с использованием PostSharp
41 /// </summary>
42 public class NewImplementation: DependencyObject
43 {44 [DependencyProperty(0)]
45 public int DemoInt32
46 {47 get { throw new NotImplementedException(); }
48 set { throw new NotImplementedException(); }
49 } 50 51 [DependencyProperty("Default String Value")]
52 public string DemoString
53 {54 get { throw new NotImplementedException(); }
55 set { throw new NotImplementedException(); }
56 } 57 } 58 59 60 61 /**************************************************************
62 Вот тут всё "колдунство"
63 *************************************************************/
64 65 /// <summary>
66 /// Магический аттрибут, превращающий свойство в DependencyProperty
67 /// ВНИМАНИЕ! реализация свойства полностью замещается!
68 /// </summary>
69 [Serializable, MulticastAttributeUsage(MulticastTargets.Property)]
70 public sealed class DependencyPropertyAttribute: CompoundAspect
71 {72 private object defaultValue = null;
73 /// <summary>
74 /// Значение по умолчанию
75 /// </summary>
76 public object DefaultValue{ get { return defaultValue; } }
77 /// <summary>
78 /// Конструирует аттрибут
79 /// </summary>
80 /// <param name="defaultValue">Значение свойства по умолчанию</param>
81 public DependencyPropertyAttribute(object defaultValue)
82 {83 this.defaultValue = defaultValue;
84 } 85 86 /// <summary>
87 /// Проверка допустимости применения аспекта
88 /// </summary>
89 /// <param name="element">цель аспекта</param>
90 /// <returns>допустимость применения аспекта</returns>
91 public override bool CompileTimeValidate(object element)
92 {93 if(!base.CompileTimeValidate(element))
94 return false;
95 PropertyInfo pi = element as PropertyInfo;
96 if(pi==null)
97 return false;
98 if(!typeof(DependencyObject).IsAssignableFrom(pi.DeclaringType))
99 return false;
100 if(!pi.CanRead || !pi.CanWrite)
101 return false;
102 if(pi.GetSetMethod().IsStatic || pi.GetGetMethod().IsStatic)
103 return false;
104 return true;
105 } 106 107 /// <summary>
108 /// Заполнение коллекции аспектов
109 /// </summary>
110 /// <param name="element">цель аспекта</param>
111 /// <param name="c">набор аспектов</param>
112 public override void ProvideAspects(object element, LaosReflectionAspectCollection c)
113 {114 PropertyInfo pi = (PropertyInfo) element;
115 c.AddAspect(pi.GetSetMethod(), new MyAspect(pi, false, this));
116 c.AddAspect(pi.GetGetMethod(), new MyAspect(pi, true, this));
117 } 118 119 private static readonly object lockObject = new object();
120 private static readonly Dictionary<PropertyInfo, DependencyProperty> dictionary
121 = new Dictionary<PropertyInfo, DependencyProperty>();
122 123 /// <summary>
124 /// Регистрация/поиск DependencyProperty
125 /// </summary>
126 /// <param name="pi">свойство</param>
127 /// <returns>экземпляр DependencyProperty</returns>
128 private DependencyProperty registerProperty(PropertyInfo pi)
129 {130 lock(lockObject)
131 {132 DependencyProperty value;
133 if (dictionary.TryGetValue(pi, out value))
134 return value;
135 else
136 {137 PropertyMetadata propertyMetadata;
138 propertyMetadata = new PropertyMetadata(DefaultValue);
139 DependencyProperty dependencyProperty =
140 DependencyProperty.Register(pi.Name,
141 pi.PropertyType, pi.DeclaringType, 142 propertyMetadata); 143 dictionary.Add(pi, dependencyProperty);144 return dependencyProperty;
145 } 146 } 147 } 148 149 /// <summary>
150 /// Поиск DependencyProperty
151 /// </summary>
152 /// <param name="pi">свойство</param>
153 /// <returns>экземпляр DependencyProperty</returns>
154 public static DependencyProperty Get(PropertyInfo pi)
155 {156 lock(lockObject)
157 {158 DependencyProperty value;
159 if(dictionary.TryGetValue(pi, out value))
160 return value;
161 else
162 return null;
163 } 164 } 165 166 /// <summary>
167 /// Поиск DependencyProperty
168 /// </summary>
169 /// <param name="type">тип - владелец свойства</param>
170 /// <param name="Name">наименование свойства</param>
171 /// <returns>экземпляр DependencyProperty</returns>
172 public static DependencyProperty Get(Type type, string Name)
173 {174 PropertyInfo pi = type.GetProperty(Name, BindingFlags.Public | BindingFlags.Instance);
175 return Get(pi);
176 } 177 178 /// <summary>
179 /// Непосредственно аспект, заменюющий реализацию Get/Set для свойства
180 /// </summary>
181 [Serializable]
182 private sealed class MyAspect : ImplementMethodAspect
183 {184 private readonly PropertyInfo pi;
185 private bool outDirection;
186 [NonSerialized] private DependencyProperty prop;
187 private DependencyPropertyAttribute parent;
188 189 /// <summary>
190 /// Конструктор
191 /// </summary>
192 /// <param name="pi">свойство к которому применён аспект</param>
193 /// <param name="outDirection">если true то замещаем Get иначе замещаем Set</param>
194 /// <param name="parent"></param>
195 public MyAspect(PropertyInfo pi, bool outDirection, DependencyPropertyAttribute parent)
196 {197 this.pi = pi;
198 this.outDirection = outDirection;
199 this.parent = parent;
200 } 201 202 /// <summary>
203 /// Инициализация рантайма после десериализации
204 /// </summary>
205 /// <param name="method"></param>
206 public override void RuntimeInitialize(MethodBase method)
207 {208 base.RuntimeInitialize(method);
209 // регистрируем Dependency свойство
210 // делаем это в тут а не в конструкторе потому что в Runtime
211 // конструктор не вызывается
212 prop = parent.registerProperty(pi); 213 } 214 215 /// <summary>
216 /// Замещение реализации
217 /// </summary>
218 /// <param name="e"></param>
219 public override void OnExecution(MethodExecutionEventArgs e)
220 {221 if(outDirection)
222 e.ReturnValue = ((DependencyObject)e.Instance).GetValue(prop);
223 else
224 ((DependencyObject)e.Instance).SetValue(prop, e.GetArguments()[0]);
225 } 226 } 227 } 228 }
|
Засада в WPF |
1 using System;
2 using System.Windows;
3 using System.Windows.Controls;
4 using System.Windows.Input;
5 6 class MainWindow: Window
7 {8 class MyCommand: ICommand
9 {10 private Window owner;
11 12 public MyCommand(Window owner)
13 {14 this.owner = owner;
15 } 16 17 public event EventHandler CanExecuteChanged;
18 19 public void Execute(object parameter)
20 {21 MessageBox.Show(owner, "Command Executed");
22 } 23 24 public bool CanExecute(object parameter)
25 {26 return parameter != null;
27 } 28 29 public void update()
30 {31 if(CanExecuteChanged!=null)
32 CanExecuteChanged(this,EventArgs.Empty);
33 } 34 } 35 36 private Button commandSource;
37 private MyCommand command;
38 39 public MainWindow()
40 {41 StackPanel p = new StackPanel();
42 Content = p; 43 44 Button b = new Button();
45 b.Content = "Test";
46 b.Click += B_OnClick; 47 p.Children.Add(b);48 b = new Button();
49 b.Content = "Command";
50 b.Command = command = new MyCommand(this);
51 p.Children.Add(b); 52 commandSource = b;53 SizeToContent = SizeToContent.WidthAndHeight;
54 } 55 56 private void B_OnClick(object sender, RoutedEventArgs e)
57 { 58 commandSource.CommandParameter =59 commandSource.CommandParameter == null ? this : null;
60 61 // Без этой строчки не работает
62 command.update(); 63 64 Title = 65 (commandSource.CommandParameter == null).ToString();
66 } 67 68 [STAThread]
69 static void Main()
70 {71 (new Application()).Run(new MainWindow());
72 } 73 }
|
S.T.A.L.K.E.R.: Shadow of Chernobyl |
|
Сериализуем несериализуемое ;) |
1 using System;
2 using System.IO;
3 using System.Runtime.Serialization.Formatters.Binary;
4 using System.Xml;
5 using System.Xml.Schema;
6 using System.Xml.Serialization;
7 8 namespace dimzon.Utils
9 {10 [Serializable]
11 public sealed class XmlSerializable<T>: IXmlSerializable
12 { 13 14 private static readonly BinaryFormatter bf = new BinaryFormatter();
15 private T originalValue;
16 17 public static implicit operator T(XmlSerializable<T> x)
18 {19 return x.originalValue;
20 } 21 22 public static implicit operator XmlSerializable<T>(T x)
23 {24 XmlSerializable<T> a = new XmlSerializable<T>();
25 a.originalValue = x;26 return a;
27 } 28 29 #region IXmlSerializable Members
30 31 public XmlSchema GetSchema()
32 {33 return null;
34 } 35 36 public void ReadXml(XmlReader reader)
37 {38 using(MemoryStream memoryStream =new MemoryStream(Convert.FromBase64String(reader.ReadString())))
39 { 40 T[] a = (T[]) bf.Deserialize(memoryStream); 41 originalValue = a[0]; 42 } 43 } 44 45 public void WriteXml(XmlWriter writer)
46 {47 T[] a = new T[1];
48 a[0] = originalValue;49 using(MemoryStream memoryStream = new MemoryStream())
50 { 51 bf.Serialize(memoryStream, a); 52 memoryStream.Flush();53 writer.WriteString(Convert.ToBase64String(memoryStream.ToArray()));
54 } 55 } 56 57 #endregion
58 } 59 }
|
Забавная фотожаба... |
|
Сделай сам... |


|
WPF и обработка исключений |
1 using System;
2 using System.Windows;
3 4 class ExceptionDemoForm: Window
5 {6 [STAThread]
7 public static void Main(string[] args)
8 {9 Application application = new Application();
10 ExceptionDemoForm form = new ExceptionDemoForm();
11 application.Run(form); 12 } 13 14 public ExceptionDemoForm()
15 {16 Title = "title of ExceptionDemoForm";
17 Loaded += windowLoaded; 18 } 19 20 private void windowLoaded(object sender, RoutedEventArgs e)
21 {22 Content = "Before Exception";
23 throw new ApplicationException("Some Exception");
24 Content = "After Exception" ;
25 } 26 }
|
Полураспад |



|
Полезные ссылки на библиотеки |
|
THE CAKE IS A LIE!!!! |


|
Сказка о том как садовый гномик в космос летал... |
Около месяца назад, когда я был на полпути в написании рецензии на эпизод 2, Дуг Ломбарди, PR менеджер валв, спросил меня, известно ли мне что-либо о "гномьем" достижении.
- Нет
- Ты находил гнома в начале игры?
- Ага
- Его надо запихнуть в ракету перед стартом.
- Но ведь это самый конец игры?
- Ага
- Но это же значит, что надо ...
- Ага
- Черт возьми! Я это сделаю!
Через месяц или около того, я сделал.
Очевидно, каждый раз, когда вы уверены, что будете возвращаться в какую-либо зону, вы можете поставить его на земалю и отправиться в одиночку. Моя склонность бросать его в местах, где я знал, что случится что-то значительное, пару раз стоила мне моего гнома.
|
Half-Life 2: Episode Two |


|
Ржунемагу |
|