MVVM: рдПрдХ рдирдпрд╛ рд░реВрдк

рдЪреЗрддрд╛рд╡рдиреА!
рдПрдорд╡реАрд╡реАрдПрдо рдкреИрдЯрд░реНрди рдкрд░ рдЕрдзрд┐рдХ рд╣рд╛рд▓рд┐рдпрд╛ рдФрд░ рдкреНрд░рдЧрддрд┐рд╢реАрд▓ рд╕рд╛рдордЧреНрд░реА рд▓реЗрдЦ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдПрдпрд░реЛ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдореЙрдбрд▓ рдкреИрдЯрд░реНрди рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдП рдЧрдП рд╣реИрдВ рдФрд░ рд▓реЗрдЦреЛрдВ рдХреА рдЕрдЧрд▓реА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рд╣реИ ред

рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛

рдХреБрдЫ рд╕рдордп рдкрд╣рд▓реЗ рдореИрдВрдиреЗ рдПрдХ рдореБрдлреНрдд рдЯреЗрдХреНрд╕реНрдЯ рдПрдбрд┐рдЯрд░ рдХреЛ рдПрдХ рд╕реБрдВрджрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдФрд░ WPF рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдкрд░ рд╡рд┐рд╕реНрддреГрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ред рдореБрдЭреЗ рдмрд╣реБрдд рд╕реА рддрдХрдиреАрдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рдореМрдХрд╛ рдорд┐рд▓рд╛, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдХреБрдЫ рдЕрдиреБрднрд╡ рдкреНрд░рд╛рдкреНрдд рд╣реБрдП рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдореИрдВ рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рд╡реНрдпрд╛рдкрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП

WPF, рд╕рд┐рд▓реНрд╡рд░рд▓рд╛рдЗрдЯ рдФрд░ WinPhone рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ MVVM (рдореЙрдбрд▓ - рджреГрд╢реНрдп - ViewModel) рдбрд┐рдЬрд╛рдЗрди рдкреИрдЯрд░реНрди рд╕реЗ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЕрд╡рдЧрдд рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрджрд┐ рдЖрдк рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдереЛрдбрд╝рд╛ рдФрд░ рдХрд▓реНрдкрдирд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдХреБрдЫ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдереЛрдбрд╝рд╛ рд╕рд╛ рднреА, рдореИрдВ рдЖрд╢реНрд╡рд╕реНрдд рдХрд░рдиреЗ рдХреА рд╣рд┐рдореНрдордд рдХрд░рддрд╛ рд╣реВрдБ, рдХреНрд░рд╛рдВрддрд┐рдХрд╛рд░реАред

рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдореЗрдиреВ, рдЯреВрд▓рдмрд╛рд░ рдФрд░ рд╕реНрдЯреЗрдЯрд╕ рдмрд╛рд░ рдХреЗ рд╕рд╛рде рдПрдХ рдЯреЗрдХреНрд╕реНрдЯ рдПрдбрд┐рдЯрд░ рдХреА рдПрдХ рдХреНрд▓рд╛рд╕рд┐рдХ рд╡рд┐рдВрдбреЛ (рджреГрд╢реНрдп) рд╣реИ, рдЬрд┐рд╕реЗ рдЖрдк рдЪрд╛рд╣реЗрдВ рддреЛ рдЫрд┐рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдореЗрдВ рд╡рд┐рдВрдбреЛ рдХреА рд╕реНрдерд┐рддрд┐ рдФрд░ рдЖрдХрд╛рд░, рд╕рд╛рде рд╣реА рд╕рд╛рде рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдВрдж рд╣реЛрдиреЗ рдкрд░ рддрддреНрд╡реЛрдВ рдХреА рджреГрд╢реНрдп рд╕реНрдерд┐рддрд┐ рдФрд░ рдлрд┐рд░ рдЙрдиреНрд╣реЗрдВ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рд╕реЗ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред

рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рд╕рдорд╛рдзрд╛рди рдЬреЛ рддреБрд░рдВрдд рджрд┐рдорд╛рдЧ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рд╡рд╣ рдмрд╛рдзреНрдпрдХрд╛рд░реА (рд╢реАрд░реНрд╖, рдмрд╛рдПрдВ, рдЪреМрдбрд╝рд╛рдИ, Heigth, ShowToolBarTray, ShowStatusBar рдФрд░ рдЕрдиреНрдп) рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдп рдореЙрдбрд▓ рдореЗрдВ рдХрдИ рдЕрддрд┐рд░рд┐рдХреНрдд рдЧреБрдг рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рдЕрдкрдиреЗ рдорд╛рдиреЛрдВ рдХреЛ рд╕рд╣реЗрдЬреЗрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдПред рд▓реЗрдХрд┐рди рдЪрд▓реЛ рдЬрд▓реНрджреА рдордд рдХрд░реЛ ... рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рджреГрд╢реНрдп рдореЙрдбрд▓ рдмрдирд╛рдирд╛ рд╕рдВрднрд╡ рд╣реИ рдЬреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдЧрд╛, рдЗрд╕рд▓рд┐рдП рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдХрд┐рд╕реА рдЕрддрд┐рд░рд┐рдХреНрдд рд▓рд╛рдЗрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ?

рдореИрдВ рддреБрд░рдВрдд рдирдореВрдирд╛ рдЖрд╡реЗрджрди рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ рдЬреЛ рдореИрдВрдиреЗ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЗрд╕ рд▓реЗрдЦ ( рдПрдХ рдпрд╛ рджреЛ рд▓рд┐рдВрдХ) рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдерд╛ , рдпрд╣ рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдФрд░ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреА рд╕реБрдВрджрд░рддрд╛ рдХреЛ рдорд╣рд╕реВрд╕ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред рдпрд╣рд╛рдВ рдореИрдВ рдХреЛрдб рдХреЗ рдХреБрдЫ рднрд╛рдЧ рдмрддрд╛рдКрдВрдЧрд╛ рдЬрд┐рди рдкрд░ рдЖрдкрдХреЛ рд╡рд┐рд╢реЗрд╖ рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред

WPF рдореЗрдВ, рдкреНрд░реЙрдкрд░реНрдЯреА рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдХреНрд╕рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд░рдгреА рддрддреНрд╡реЛрдВ рдХреЗ рд▓рд┐рдП рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рднреА рд╣реЛрддреА рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢рд╛рдпрдж рд╣реА рдХрднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣рд╛рдБ рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдирдП рдХреНрд╖рд┐рддрд┐рдЬ рдЦреЛрд▓рддрд╛ рд╣реИред рдЖрдЗрдП рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЛ рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдЬрд╣рд╛рдВ рд╕реВрдЪрдХрд╛рдВрдХ рдХреБрдВрдЬреА рдЙрд╕ рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдирд╛рдо рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рдЗрд╕рдХрд╛ рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рд▓реЗрдХрд┐рди рд╣рдо рдЗрди рдореВрд▓реНрдпреЛрдВ рдХреЛ рдХреИрд╕реЗ рдмреЗрд╣рддрд░ рд░рдЦрддреЗ рд╣реИрдВ? рдЖрдЗрдП рджреЗрдЦреЗрдВ рдореЙрдбрд▓ рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ! рд▓реЗрдХрд┐рди? .. рдпрд╣ рдПрдХ рдбреАрдЯреАрдУ рдСрдмреНрдЬреЗрдХреНрдЯ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЙрдиреНрд╣реЗрдВ рдбрд┐рд╕реЗрд░рд┐рдПрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХреЛ рдЕрдХреНрд╕рд░ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЕрдиреНрдп рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдбрд┐рд╕реЗрд░рд┐рдПрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЖрдорддреМрд░ рдкрд░ рдмрд┐рдирд╛ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдПрдХ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ? рдХреНрдпрд╛ рдпрд╣ рдЖрдкрдХреЛ рдкреНрд░рддреАрдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдирд┐рд░реНрдорд╛рдг рдореЗрдВ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рдирд╛ рдХреБрдЫ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдерд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрдм рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдпрд╛ рд╣рдЯрд╛рддреЗ рд╕рдордп, рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдг рдЯреВрдЯ рдЧрдП, рдФрд░ рдЙрдиреНрд╣реЗрдВ рднреА рдареАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдП рдЧрдП рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдПрдХ рд╣реА рд░рд╣рд╛?

рдЗрд╕рд▓рд┐рдП, рд╣рдо рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЗрдВрдЬреЗрдХреНрд╢рдиреЛрдВ рдХреЛ рдордирд╛ рдХрд░ рджреЗрдВрдЧреЗ, рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдРрд╕реЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдиреНрдп рддрд░реАрдХреЗ рд╣реИрдВ, рдФрд░ [рдбреЗрдЯрд╛рдХрд╛рд░реНрдЯ] рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЬрд┐рди рдЧреБрдгреЛрдВ рдХреЛ [DataMember] рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рдХреНрд░рдордмрджреНрдз рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ (рдЗрди рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдХреНрд░рдордмрджреНрдзрддрд╛ рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИ)ред

рдЕрдм рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╕реНрдЯреЛрд░ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдВред

public static class Store { private static readonly Dictionary<Type, object> StoredItemsDictionary = new Dictionary<Type, object>(); public static TItem OfType<TItem>(params object[] args) where TItem : class { var itemType = typeof (TItem); if (StoredItemsDictionary.ContainsKey(itemType)) return (TItem) StoredItemsDictionary[itemType]; var hasDataContract = Attribute.IsDefined(itemType, typeof (DataContractAttribute)); var item = hasDataContract ? Serializer.DeserializeDataContract<TItem>() ?? (TItem) Activator.CreateInstance(itemType, args) : (TItem) Activator.CreateInstance(itemType, args); StoredItemsDictionary.Add(itemType, item); return (TItem) StoredItemsDictionary[itemType]; } public static void Snapshot() { StoredItemsDictionary .Where(p => Attribute.IsDefined(p.Key, typeof (DataContractAttribute))) .Select(p => p.Value).ToList() .ForEach(i => i.SerializeDataContract()); } } 


рдпрд╣рд╛рдВ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ - рдХреЗрд╡рд▓ рджреЛ рддрд░реАрдХреЗред рд╕рдВрднрд╡рддрдГ рдЯрд╛рдЗрдк рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдПрдХ рд╕реНрдерд┐рд░ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рд╕рдВрднрд╡рддрдГ рдЗрд╕реЗ рдбрд┐рд╕реЗрд░рд▓рд╛рдЗрдЬрд╝ рдХрд░рдирд╛ рд╣реИ, рдФрд░ рд╕реНрдиреИрдкрд╢реЙрдЯ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ рдХрд╛ "рд╕реНрдиреИрдкрд╢реЙрдЯ" рд▓реЗрддрд╛ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рдХреНрд░рдордмрджреНрдз рдХрд░рддрд╛ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреЛ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд░реНрдЧ рдХреЗ рдПрдХреНрдЬрд╝рд┐рдЯ рд╣реИрдВрдбрд▓рд░ рдореЗрдВред

рдФрд░ рдПрдХ рдЬрд╕рди рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рд▓рд┐рдЦреЗрдВред

  public static class Serializer { public const string JsonExtension = ".json"; public static readonly List<Type> KnownTypes = new List<Type> { typeof (Type), typeof (Dictionary<string, string>), typeof (SolidColorBrush), typeof (MatrixTransform), }; public static void SerializeDataContract(this object item, string file = null, Type type = null) { try { type = type ?? item.GetType(); if (string.IsNullOrEmpty(file)) file = type.Name + JsonExtension; var serializer = new DataContractJsonSerializer(type, KnownTypes); using (var stream = File.Create(file)) { var currentCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; serializer.WriteObject(stream, item); Thread.CurrentThread.CurrentCulture = currentCulture; } } catch (Exception exception) { Trace.WriteLine("Can not serialize json data contract"); Trace.WriteLine(exception.StackTrace); } } public static TItem DeserializeDataContract<TItem>(string file = null) { try { if (string.IsNullOrEmpty(file)) file = typeof (TItem).Name + JsonExtension; var serializer = new DataContractJsonSerializer(typeof (TItem), KnownTypes); using (var stream = File.OpenRead(file)) { var currentCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; var item = (TItem) serializer.ReadObject(stream); Thread.CurrentThread.CurrentCulture = currentCulture; return item; } } catch { return default(TItem); } } } 


рджреЗрдЦрдиреЗ рдХреЗ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдЖрдзрд╛рд░ рд╡рд░реНрдЧ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИред

  [DataContract] public class ViewModelBase : PropertyNameProvider, INotifyPropertyChanging, INotifyPropertyChanged { protected Dictionary<string, object> Values = new Dictionary<string, object>(); private const string IndexerName = System.Windows.Data.Binding.IndexerName; /* "Item[]" */ public event PropertyChangingEventHandler PropertyChanging = (sender, args) => { }; public event PropertyChangedEventHandler PropertyChanged = (sender, args) => { }; public object this[string key] { get { return Values.ContainsKey(key) ? Values[key] : null; } set { RaisePropertyChanging(IndexerName); if (Values.ContainsKey(key)) Values[key] = value; else Values.Add(key, value); RaisePropertyChanged(IndexerName); } } public object this[string key, object defaultValue] { get { if (Values.ContainsKey(key)) return Values[key]; Values.Add(key, defaultValue); return defaultValue; } set { this[key] = value; } } public void RaisePropertyChanging(string propertyName) { PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); } public void RaisePropertyChanged(string propertyName) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } [OnDeserializing] private void Initialize(StreamingContext context = default(StreamingContext)) { if (PropertyChanging == null) PropertyChanging = (sender, args) => { }; if (PropertyChanged == null) PropertyChanged = (sender, args) => { }; if (Values == null) Values = new Dictionary<string, object>(); } } 


рд╣рдореЗрдВ рдЫреЛрдЯреА рд╢реНрд░реЗрдгреА рдХреЗ рд╕рдВрдкрддреНрддрд┐рдиреИрдордкреНрд░реЛрдЗрдбрд░ рд╕реЗ рднреА рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ, рдЬреЛ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд▓рдВрдмреЛрджрд░ рднрд╛рд╡ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред

  [DataContract] public class PropertyNameProvider { public static string GetPropertyName<T>(Expression<Func<T>> expression) { var memberExpression = expression.Body as MemberExpression; var unaryExpression = expression.Body as UnaryExpression; if (unaryExpression != null) memberExpression = unaryExpression.Operand as MemberExpression; if (memberExpression == null || memberExpression.Member.MemberType != MemberTypes.Property) throw new Exception("Invalid lambda expression format."); return memberExpression.Member.Name; } } 


рдЦреИрд░, рдЗрд╕ рд╕реНрддрд░ рдкрд░ рд╣рдордиреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдЧреБрдгреЛрдВ рдХреЛ рдмрд╛рдВрдзрдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИред Xaml рдореЗрдВ рдЖрдк рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлреЙрд░реНрдо рдХреЗ рднрд╛рд╡ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ

рдКрдБрдЪрд╛рдИ = "{рдмрд╛рдЗрдВрдбрд┐рдВрдЧ '[рдКрдБрдЪрд╛рдИ, 600]', рдореЛрдб = рдЯреВрд╡реЗ}"

рдЬрд╣рд╛рдВ рдкрд╣рд▓рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдирд╛рдо рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛ (рд╡реИрдХрд▓реНрдкрд┐рдХ) рдЗрд╕рдХрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореВрд▓реНрдп рд╣реИред

рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреБрдЫ рд╣рдж рддрдХ рдорд╛рдирдХ IDataErrorInfo рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдпрд╛рдж рджрд┐рд▓рд╛рддрд╛ рд╣реИред рд╣рдо рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд░рддреЗ? рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ, рд▓реЗрдХрд┐рди рдЪрд▓реЛ рдЬрд▓реНрджреА рдордд рдХрд░реЛ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦреЗрдВ ... рдЖрдЗрдП рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреЗ рдкреБрди: рдирд┐рд░реНрдзрд╛рд░рдг рдХреЗ рд╕рд╛рде рдЦреЗрд▓рддреЗ рд╣реИрдВред рд╣рд░ рдХреЛрдИ ICommand рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдпрд╛рдж рдХрд░рддрд╛ рд╣реИ, рдФрд░ WPF рдореЗрдВ рдЕрднреА рднреА рдПрдХ рдЕрдЪреНрдЫрд╛ рддрдВрддреНрд░ рд╣реИ рдХрд┐ рдХреИрд╕реЗ RoutedCommands рдФрд░ CommandBindings рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕ рддрд░рд╣ рд╕реЗ рджреГрд╢реНрдп рдореЙрдбрд▓ рдореЗрдВ рдЖрджреЗрд╢реЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд▓рд┐рдЦрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред

  this[ApplicationCommands.Save].CanExecute += (sender, args) => args.CanExecute = HasChanged; this[ApplicationCommands.New].CanExecute += (sender, args) => { args.CanExecute = !string.IsNullOrEmpty(FileName) || !string.IsNullOrEmpty(Text); }; this[ApplicationCommands.Help].Executed += (sender, args) => MessageBox.Show("Muse 2014"); this[ApplicationCommands.Open].Executed += (sender, args) => Open(); this[ApplicationCommands.Save].Executed += (sender, args) => Save(); this[ApplicationCommands.SaveAs].Executed += (sender, args) => SaveAs(); this[ApplicationCommands.Close].Executed += (sender, args) => Environment.Exit(0); this[ApplicationCommands.New].Executed += (sender, args) => { Text = string.Empty; FileName = null; HasChanged = false; }; 


рдЦреИрд░, рдЧреБрдгреЛрдВ рдФрд░ рд▓рдВрдмреЛрджрд░ рднрд╛рд╡реЛрдВ рдХреА рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЕрдзрд┐рд╕реВрдЪрдирд╛ рдХреЗ рдмрд┐рдирд╛ рдПрдХ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреНрдпрд╛ рд╣реИ? рдпрд╣ рд╡реИрд╕реЗ рднреА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

  public string Text { get { return Get(() => Text); } set { Set(() => Text, value); } } 


рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдЕрдЧрд░ ... рдПрдХ рдХрдорд╛рдВрдбрдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреА рддрд░рд╣ рдПрдХ рдкреНрд░реЙрдкрд░реНрдЯреАрдмрд╛рдЗрдВрдб рдмрдирд╛рдПрдВ рдФрд░ рдлрд┐рд░ рд╕реЗ рдЗрдВрдбреЗрдХреНрд╕рд░ рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рд╕рд╛ рдЦреЗрд▓реЗрдВ?

  this[() => Text].PropertyChanged += (sender, args) => HasChanged = true; this[() => FontSize].Validation += () => 4.0 < FontSize && FontSize < 128.0 ? null : "Invalid font size"; 


рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИ, рд╣реИ рдирд╛?

рдФрд░, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рд╣рдорд╛рд░реЗ рдЪрдорддреНрдХрд╛рд░ рджреГрд╢реНрдп рдореЙрдбрд▓ред

  [DataContract] public class ViewModel : ViewModelBase, IDataErrorInfo { public ViewModel() { Initialize(); } string IDataErrorInfo.this[string propertyName] { get { return PropertyBindings.ContainsKey(propertyName) ? PropertyBindings[propertyName].InvokeValidation() : null; } } public PropertyBinding this[Expression<Func<object>> expression] { get { var propertyName = GetPropertyName(expression); if (!PropertyBindings.ContainsKey(propertyName)) PropertyBindings.Add(propertyName, new PropertyBinding(propertyName)); return PropertyBindings[propertyName]; } } public CommandBinding this[ICommand command] { get { if (!CommandBindings.ContainsKey(command)) CommandBindings.Add(command, new CommandBinding(command)); return CommandBindings[command]; } } public string Error { get; protected set; } public Dictionary<ICommand, CommandBinding> CommandBindings { get; private set; } public Dictionary<string, PropertyBinding> PropertyBindings { get; private set; } public CancelEventHandler OnClosing = (o, e) => { }; public TProperty Get<TProperty>(Expression<Func<TProperty>> expression, TProperty defaultValue = default(TProperty)) { var propertyName = GetPropertyName(expression); if (!Values.ContainsKey(propertyName)) Values.Add(propertyName, defaultValue); return (TProperty) Values[propertyName]; } public void Set<TProperty>(Expression<Func<TProperty>> expression, TProperty value) { var propertyName = GetPropertyName(expression); RaisePropertyChanging(propertyName); if (!Values.ContainsKey(propertyName)) Values.Add(propertyName, value); else Values[propertyName] = value; RaisePropertyChanged(propertyName); } public void RaisePropertyChanging<TProperty>(Expression<Func<TProperty>> expression) { var propertyName = GetPropertyName(expression); RaisePropertyChanging(propertyName); } public void RaisePropertyChanged<TProperty>(Expression<Func<TProperty>> expression) { var propertyName = GetPropertyName(expression); RaisePropertyChanged(propertyName); } [OnDeserializing] private void Initialize(StreamingContext context = default(StreamingContext)) { CommandBindings = new Dictionary<ICommand, CommandBinding>(); PropertyBindings = new Dictionary<string, PropertyBinding>(); PropertyChanging += OnPropertyChanging; PropertyChanged += OnPropertyChanged; } private void OnPropertyChanging(object sender, PropertyChangingEventArgs e) { var propertyName = e.PropertyName; if (!PropertyBindings.ContainsKey(propertyName)) return; var binding = PropertyBindings[propertyName]; if (binding != null) binding.InvokePropertyChanging(sender, e); } private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { var propertyName = e.PropertyName; if (!PropertyBindings.ContainsKey(propertyName)) return; var binding = PropertyBindings[propertyName]; if (binding != null) binding.InvokePropertyChanged(sender, e); } } 


рдЕрдм рд╣рдо рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╢рд╕реНрддреНрд░ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдкреВрд░реНрдгрддрд╛ рдХреА рдХреЛрдИ рд╕реАрдорд╛ рдирд╣реАрдВ рд╣реИред рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рджреГрд╢реНрдп рдореЙрдбрд▓ C # рдХреЛрдб рдореЗрдВ рдЗрд╕рдХреЗ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ (рджреГрд╢реНрдп) рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ, рд▓реЗрдХрд┐рди xaml рдореЗрдВ рд╕реАрдзреЗ рдЗрд╕ рдмрдВрдзрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдХрд┐рддрдирд╛ рд╕реБрдВрджрд░ рд╣реЛрдЧрд╛! рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЗрдВрдЬреЗрдХреНрд╢рди рдХреЗ рд╣рдорд╛рд░реЗ рдЗрдирдХрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдпрд╛рдж рд░рдЦреЗрдВ? рдЗрд╕рд▓рд┐рдП рд╡рд╣ рд╣рдореЗрдВ рдРрд╕рд╛ рдЕрд╡рд╕рд░ рджреЗрддрд╛ рд╣реИред рдорд╛рд░реНрдХрдЕрдк * рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╡рд┐рд╕реНрддрд╛рд░ рд▓рд┐рдЦреЗрдВред

  public class StoreExtension : MarkupExtension { public StoreExtension(Type itemType) { ItemType = itemType; } [ConstructorArgument("ItemType")] public Type ItemType { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { var service = (IProvideValueTarget) serviceProvider.GetService(typeof (IProvideValueTarget)); var frameworkElement = service.TargetObject as FrameworkElement; var dependancyProperty = service.TargetProperty as DependencyProperty; var methodInfo = typeof(Store).GetMethod("OfType").MakeGenericMethod(ItemType); var item = methodInfo.Invoke(null, new object[] { new object[0] }); if (frameworkElement != null && dependancyProperty == FrameworkElement.DataContextProperty && item is ViewModel) { var viewModel = (ViewModel) item; frameworkElement.CommandBindings.AddRange(viewModel.CommandBindings.Values); var window = frameworkElement as Window; if (window != null) viewModel.OnClosing += (o, e) => { if (!e.Cancel) window.Close(); }; frameworkElement.Initialized += (sender, args) => frameworkElement.DataContext = viewModel; return null; } return item; } } 


рд╡реЛрдЗрд▓рд╛, рдХрд┐рдпрд╛!

DataContext = "{рд╕реНрдЯреЛрд░ рджреГрд╢реНрдпрдореЙрдбрд▓: MainViewModel}"

рдореИрдВ рдЗрд╕ рддрдереНрдп рдкрд░ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди, рдирд┐рдпрдВрддреНрд░рдг рди рдХреЗрд╡рд▓ рдбреЗрдЯрд╛рдХреЛрдЯреЗрдХреНрд╕реНрдЯ рдХреЛ рдмрджрд▓рддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдХрдорд╛рдВрдбрдмрд╛рдЗрдВрдбрд┐рдВрдЧ рд╕рдВрдЧреНрд░рд╣ рдХреЛ рд╡реНрдпреВ рдореЙрдбрд▓ рд╕реЗ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдЖрдмрд╛рджреА рд╣реИред

(* рддрд╛рдХрд┐ рдорд╛рд░реНрдХрдЕрдк рдХреЗ рд▓рд┐рдП рдЙрдкрд╕рд░реНрдЧ "{Foundation: Store viewModels: MainViewModel}" рдЬреИрд╕реЗ рдЙрдкрд╕рд░реНрдЧ рди рд▓рд┐рдЦреЗрдВ, рдЙрдиреНрд╣реЗрдВ рдПрдХ рдЕрд▓рдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЙрд╕реА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдЖрдкрдХреЛ рдЕрд╕реЗрдВрдмрд▓реА рдореЗрдВ рдХреБрдЫ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред
 [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Foundation")] [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Foundation.Converters")] [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Foundation.MarkupExtensions")] 
)

рдЗрд╕реА рдкреНрд░рдХрд╛рд░, рд╣рдо рдКрдкрд░ рдЪрд░реНрдЪрд╛ рдХрд┐рдП рдЧрдП рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдмрдВрдзрди рдХреЛ рд╕реБрд╢реЛрднрд┐рдд рдХрд░рддреЗ рд╣реИрдВред

  public class ViewModelExtension : MarkupExtension { private static readonly BooleanConverter BooleanToVisibilityConverter = new BooleanConverter { OnTrue = Visibility.Visible, OnFalse = Visibility.Collapsed, }; private FrameworkElement _targetObject; private DependencyProperty _targetProperty; public ViewModelExtension() { } public ViewModelExtension(string key) { Key = key; } public ViewModelExtension(string key, object defaultValue) { Key = key; DefaultValue = defaultValue; } public string Key { get; set; } public string StringFormat { get; set; } public string ElementName { get; set; } public object DefaultValue { get; set; } public object FallbackValue { get; set; } public object TargetNullValue { get; set; } public IValueConverter Converter { get; set; } public RelativeSource RelativeSource { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { var service = (IProvideValueTarget) serviceProvider.GetService(typeof (IProvideValueTarget)); _targetProperty = service.TargetProperty as DependencyProperty; _targetObject = service.TargetObject as FrameworkElement; if (_targetObject == null || _targetProperty == null) return this; var key = Key; if (_targetProperty == UIElement.VisibilityProperty && string.IsNullOrWhiteSpace(key)) key = string.Format("Show{0}", string.IsNullOrWhiteSpace(_targetObject.Name) ? _targetObject.Tag : _targetObject.Name); key = string.IsNullOrWhiteSpace(key) ? _targetProperty.Name : key; if (!string.IsNullOrWhiteSpace(StringFormat)) Key = string.Format(StringFormat, _targetObject.Tag); var index = DefaultValue == null ? key : key + "," + DefaultValue; var path = string.IsNullOrWhiteSpace(ElementName) && RelativeSource == null ? "[" + index + "]" : "DataContext[" + index + "]"; if (_targetProperty == UIElement.VisibilityProperty && Converter == null) Converter = BooleanToVisibilityConverter; var binding = new Binding(path) {Mode = BindingMode.TwoWay, Converter = Converter}; if (ElementName != null) binding.ElementName = ElementName; if (FallbackValue != null) binding.FallbackValue = FallbackValue; if (TargetNullValue != null) binding.TargetNullValue = TargetNullValue; if (RelativeSource != null) binding.RelativeSource = RelativeSource; _targetObject.SetBinding(_targetProperty, binding); return binding.ProvideValue(serviceProvider); } } 


Xaml рдореЗрдВ рдЖрдк рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:

рдЪреМрдбрд╝рд╛рдИ = "{ViewModel DefaultValue = 800}"

рдкрд░рд┐рдгрд╛рдо

рд╢рд╛рдпрдж рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рдореИрдВрдиреЗ рдмрд╣реБрдд рд╕рд╛рд░реА рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкреВрд░реНрдгрддрд╛ рдХреЗ рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд╛рде рдЦреБрдж рдХреЛ рдкрд░рд┐рдЪрд┐рдд рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред

рдЙрдкрд░реЛрдХреНрдд рд╕рднреА рдХреЛ рд╕рд╛рд░рд╛рдВрд╢рд┐рдд рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд╛рднреЛрдВ рдХреЛ рдЕрд▓рдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
- рд╕реНрд╡рдЪреНрдЫ, рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдФрд░ рд╕рдВрд░рдЪрд┐рдд рдХреЛрдбред рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рддрд░реНрдХ, рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдХрдордЬреЛрд░ рд░реВрдк рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ, рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЗ рдЖрдзрд╛рд░ рд╡рд░реНрдЧреЛрдВ рдХреЗ рдЕрдВрджрд░ рд╕рдордЭрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЗ рдареЛрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ рддрд░реНрдХ рд╣реИ рдЬреЛ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдирд┐рдпрдореЛрдВ рд╕реЗ рдирд┐рдХрдЯрддрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ;
- рд╕рдорд╛рдзрд╛рди рдХреА рд╕рд╛рджрдЧреА рдФрд░ рдмрд╣реБрдореБрдЦреА рдкреНрд░рддрд┐рднрд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХреНрд░рдорд╛рдВрдХрди рдЖрдкрдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдмрд╣реБрдд рд▓рдЪреАрд▓реЗ рдврдВрдЧ рд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ;
- IDataErrorInfo рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рддреНрдпрд╛рдкрди рдХрд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиред

рд╡рд┐рдкрдХреНрд╖:
- рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЗрдВрдЬреЗрдХреНрд╢рди рд╕реЗ рдЗрдирдХрд╛рд░ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдПрдХ рдЕрдирд┐рд╡рд╛рд░реНрдп рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ);
- рдПрдХ рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдирд┐рд╣рд┐рдд рдирд┐рд░реНрдгрдп рдЙрд╕рдХреЗ рд╕рд╛рде рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИред

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдорд╣рд╛рд░рдд рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдФрд░ рдЕрдкрдиреЗ рдирд┐рдкрдЯрд╛рди рдореЗрдВ рдХреЗрд╡рд▓ рдХреБрдЫ рдЖрдзрд╛рд░ рдХрдХреНрд╖рд╛рдПрдВ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдЖрд░рд╛рдо рд╕реЗ, рдЬрд▓реНрджреА рдФрд░ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдПрдХ рд╕рдореГрджреНрдз рдЗрдВрдЯрд░реИрдХреНрдЯрд┐рд╡ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрдмрдХрд┐ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЛ рд╕рд╛рдл рдФрд░ рдХреЙрдореНрдкреИрдХреНрдЯ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред

рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рд▓реЗрдЦ рдЖрдкрдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛! рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!

PS рдореБрдЭреЗ рдареАрдХ рд╕реЗ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╕рд┐рд▓реНрд╡рд░рд▓рд╛рдЗрдЯ рдореЗрдВ рдХреИрд╕реЗ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди WinPhone рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдкрд░ рдХреБрдЫ рдкреНрд░рддрд┐рдмрдВрдз рд╣реИрдВ (рдХреЛрдИ рдорд╛рд░реНрдХрдЕрдк рдПрдХреНрд╕рдЯреЗрдВрд╢рди, рд░реВрдЯреЗрдбрдХрд╛рдордВрдб рдФрд░ рдХрдорд╛рдВрдбрдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдирд╣реАрдВ рд╣реИрдВ), рд▓реЗрдХрд┐рди рдЖрдк рдЙрдиреНрд╣реЗрдВ рдмрд╛рдИрдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ WinPhone рд▓реЗрдЦ рдореЗрдВ рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрд┐рдд рд╣реИ : рдЙрддреНрдХреГрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рд░рд╛рд╕реНрддрд╛ ред

PPS рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдКрдкрд░ рдХрд╣рд╛, рдкреВрд░реНрдг рдкрд╛рда рдкрд╛рда рд╕рдВрдкрд╛рджрдХ рдмрдирд╛рддреЗ рд╕рдордп рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдмрддрд╛рдИ рдЧрдИ рд╕рднреА рд╡рд┐рдзрд┐рдпрд╛рдБ рд▓рд╛рдЧреВ рд╣реЛрддреА рд╣реИрдВред рдЬреЛ рд▓реЛрдЧ рд╕реГрдЬрди рдХреЗ рд▓рд┐рдП рдЖрдЦрд┐рд░рдХрд╛рд░ рдХрд┐рд╕ рдЪреАрдЬ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рд╡реЗ рдЗрд╕реЗ рдЗрд╕ рд▓рд┐рдВрдХ рдпрд╛ рдмреИрдХрдЕрдк рдкрд░ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдФрд░ рдХрд╡рд┐рддрд╛ рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рд╣реИ : рдЬреИрд╕реЗ рд╢рдмреНрджреЛрдВ рдХрд╛ рдПрдХ рдорд╛рд╕реНрдЯрд░ рдХреБрдЫ рд╡рд╛рдХреНрдпрд╛рдВрд╢реЛрдВ рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИ рдХрд┐ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╡реНрдпрдХреНрддрд┐ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рдХреНрдпрд╛ рд▓реЗрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдПрдХ рдЕрдиреБрднрд╡реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛрдб рдХреА рдХрдИ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдореБрд╢реНрдХрд┐рд▓ рдХрд╛рдо рд╣рд▓ рдХрд░рддрд╛ рд╣реИред

рдЖрдк рдХреЛ рдкреНрд░реЗрд░рдгрд╛!

~~~~~~~~~~~~~~~~~~~~~~~~~
рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ:

- рдЖрдк рдХрд┐рд╕реА рднреА рдирд┐рдпрдВрддреНрд░рдг рдХреЛ рдПрдХ рджреГрд╢реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдХрднреА-рдХрднреА рдПрдХ рдЕрд▓рдЧ рдЗрдХрд╛рдИ (рдПрдХ рдирдпрд╛ рд╡рд░реНрдЧ) рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рджреГрд╢реНрдп рдХрд╛ рдЪрдпрди рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ, рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рджреГрд╢реНрдп рдореЙрдбрд▓ рдореЗрдВ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдЬреЛрдбрд╝реЗрдВред рдореИрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рд╕рдордЭрд╛рдКрдВрдЧрд╛:

 <Window DataContext={Store viewModels:MainViewModel}> тАж <!--<TextBlock DataContext={Store viewModels:DetailsViewModel} Text={Binding Name}/>--!> <TextBlock Text={Binding Name, Source={Store viewModels:DetailsViewModel}}/> тАж </Window> 


рдпрд╣реА рд╣реИ, рд╣рдореЗрдВ рдЗрдВрдЯрд░рдлреЗрд╕ рдореЗрдВ рдХрд╣реАрдВ рдкрд░ рднреА рдирд╛рдо рдХреА рд╕рдВрдкрддреНрддрд┐ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореЗрдиреНрдпреВ рд╡реНрдпреВрдХреЛрдб рдореЗрдВ рдбрд┐рдЯреЗрд▓реНрд╕ рд╡реНрдпреВрдореЙрдбрд▓ рдХреЛ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдбрд┐рдЯреЗрд▓рд╢реЙрд░реНрдЯ рд╡реНрдпреВ рдмрдирд╛рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдХрдо рдХрдХреНрд╖рд╛рдПрдВ рд╣реИрдВ, рдФрд░ рд╕рдВрд░рдЪрдирд╛ рд╕реНрдкрд╖реНрдЯ рд╣реИред

- рд▓реЗрдЦ рдореЗрдВ рдореИрдВрдиреЗ рдореВрд▓ рд╕рд┐рджреНрдзрд╛рдВрдд рджрд┐рдЦрд╛рдП, рдЬрд┐рдирдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдЖрдк рдЬрд▓реНрджреА рдФрд░ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдЖрд╡реЗрджрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рд╕рдм рдХреБрдЫ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдХреБрд▓ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрдкрдХреЗ рдкрд╛рд╕ рд╕реБрдзрд╛рд░, рд╕рдВрд╢реЛрдзрди рдФрд░ рдХрд▓реНрдкрдирд╛ рдХрд░рдиреЗ рдХрд╛ рдЕрдзрд┐рдХрд╛рд░ рд╣реИ! рдпрд╣реА рд╡рд┐рдХрд╛рд╕ рд╣реИ, рд╕рдлрд▓рддрд╛ рд╣реИ!

Source: https://habr.com/ru/post/In208326/


All Articles