MVVMãã¿ãŒã³ã«é¢ããææ°ã®é²æ©çãªè³æã¯ã Aero Frameworkãä»ããContext Model Patternã®èšäºã§çŽ¹ä»ãããŠããã 次ã®äžé£ã®èšäºã§è©³ãã説æãããŠããŸãã
ãŸããã
ãã°ããåãç§ã¯çŸããã€ã³ã¿ãŒãã§ã€ã¹ãšWPFãã©ãããã©ãŒã ã®å¹ åºã䟿å©ãªæ©èœãåããããªãŒããã¹ããšãã£ã¿ãŒã®éçºãéå§ããŸããã å€ãã®æè¡çãªåé¡ã解決ããæ©äŒããã£ãã®ã§ãä»ã®äººãšå ±æãããçµéšãç©ãããšãã§ããŸããã
ããžãã¹ãž
WPFãSilverlightãWinPhoneã¢ããªã±ãŒã·ã§ã³ã®éçºè ã¯ãMVVMïŒã¢ãã«-ãã¥ãŒ-ViewModelïŒèšèšãã¿ãŒã³ãããç¥ã£ãŠããŸãã ããããããã«æ³ååãè¿œå ãããšããã£ãšé¢çœãããšãå€æããå¯èœæ§ããããå°ãã§ãé©åœçãªããšãä¿èšŒããŸãã
å¿ èŠã«å¿ããŠé衚瀺ã«ã§ããã¡ãã¥ãŒãããŒã«ããŒãã¹ããŒã¿ã¹ããŒãåããããã¹ããšãã£ã¿ã®ã¯ã©ã·ãã¯ãŠã£ã³ããŠïŒãã¥ãŒïŒããããšããŸãã ã¢ããªã±ãŒã·ã§ã³ã®çµäºæã®èŠçŽ ã®èŠèŠçç¶æ ãšåæ§ã«ããŠã£ã³ããŠã®äœçœ®ãšãµã€ãºãä¿åãããããã埩å ããã¿ã¹ã¯ã«çŽé¢ããŠããŸãã
ããã«é ãæ©ãŸããéåžžã®è§£æ±ºçã¯ããã€ã³ãçšã®ãã¥ãŒã¢ãã«ã«å€ãã®è¿œå ããããã£ïŒTopãLeftãWidthãHeigthãShowToolBarTrayãShowStatusBarãªã©ïŒãè¿œå ãããã®å€ããã¡ã€ã«ãªã©ã«ä¿åããããšã§ãã æ¥ãã§ã¯ãããŸãã...å¿ èŠãªæ©èœãããã©ã«ãã§å®è£ ãããããªãã¥ãŒã¢ãã«ãäœæã§ããã®ã§ãåé¡ã解決ããããã«äœåãªã³ãŒãè¡ãå¿ èŠãšããªããšãããã©ãã§ããããã
ãã®èšäºã®ããã«ç¹å¥ã«äœæãããµã³ãã«ã¢ããªã±ãŒã·ã§ã³ïŒ 1ã€ãŸãã¯2ã€ã®ãªã³ã¯ïŒãããã«ããŠã³ããŒãããããšããå§ãããŸããäž»èŠãªã¢ã€ãã¢ãç解ããã¢ãããŒãã®çŸãããæããã®ã«åœ¹ç«ã¡ãŸãã ããã§ã¯ãç¹å¥ãªæ³šæãæãå¿ èŠãããã³ãŒãã®ç¹å®ã®éšåã瀺ããŸãã
WPFã§ã¯ãããããã£ãã€ã³ãããã䜿çšãããŸããããŸãã«ãã䜿çšãããªãé åèŠçŽ ãžã®ãã€ã³ãã®å¯èœæ§ããããŸãã ããããããã§ç§ãã¡ã«æ°ããèŠéãéãããŸãã ãã¥ãŒã¢ãã«ããã£ã¯ã·ã§ããªãšããŠèããŠã¿ãŸããããã€ã³ããã¯ã¹ããŒã¯ãå€ãååŸã§ããããããã£ã®ååã«ãªããŸãã
ãããããããã®å€ãç¶æããã«ã¯ã©ãããã°ããã§ããããïŒ ãã¥ãŒã¢ãã«ãã·ãªã¢ã«åããŠã¿ãŸãããïŒ ãããã..ããã¯DTOãªããžã§ã¯ãã§ã¯ãªããä»ã®ãã©ã¡ãŒã¿ãŒãã³ã³ã¹ãã©ã¯ã¿ãŒã«ã€ã³ãžã§ã¯ãããå¿ èŠãããå Žåãå€ãã®ã§ãã©ã®ããã«ãã·ãªã¢ã©ã€ãºããŸããã ã³ã³ã¹ãã©ã¯ã¿ãŒãžã®æ³šå ¥ã¯ãããšãã°ãã©ã¡ãŒã¿ãŒãè¿œå ãŸãã¯åé€ãããšãã«ãŠããããã¹ããæ©èœããªããªãããã¹ããããªããžã§ã¯ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã¯æ¬è³ªçã«åãã§ããã«ãããããããä¿®æ£ããå¿ èŠããããªã©ãäžäŸ¿ã§ãããšã¯æãããŸããã§ãããïŒ
ãããã£ãŠã幞éãªããšã«ãã³ã³ã¹ãã©ã¯ã¿ãŒãžã®æ³šå ¥ãæåŠãããã®ãããªç®çã®ããã®ä»ã®æ¹æ³ãããã[DataContract]å±æ§ã§ãã¥ãŒã¢ãã«ãããŒã¯ãã[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()); } }
ããã§ã¯ãã¹ãŠãç°¡åã§ãããã£ã2ã€ã®æ¹æ³ã§ãã OfTypeã¯å¿ èŠãªã¿ã€ãã®ãªããžã§ã¯ãã®éçã€ã³ã¹ã¿ã³ã¹ãè¿ããå Žåã«ãã£ãŠã¯éã·ãªã¢ã«åããSnapshotã¯ã³ã³ãããŒå ã®ãªããžã§ã¯ãã®ãã¹ãããã·ã§ããããåããããããã·ãªã¢ã«åããŸãã äžè¬ã«ãã¹ãããã·ã§ããã¯ãããšãã°Applicationã¯ã©ã¹ã®Exitãã³ãã©ãŒãªã©ãã¢ããªã±ãŒã·ã§ã³ãéãããããšãã«1åã ãåŒã³åºãããšãã§ããŸãã
ãããŠãJsonã·ãªã¢ã©ã€ã¶ãŒãäœæããŸãã
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>(); } }
ãŸããå°ããªã¯ã©ã¹PropertyNameProviderããç¶æ¿ããŸããããã¯ãä»åŸã©ã ãåŒãæäœããã®ã«åœ¹ç«ã¡ãŸãã
[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ã§ã¯ã次ã®åœ¢åŒã®åŒãèšè¿°ã§ããŸã
Height = "{Binding '[Heightã600]'ãMode = TwoWay}"
ããã§ãæåã®ãã©ã¡ãŒã¿ãŒã¯ããããã£ã®ååã§ããã2çªç®ïŒãªãã·ã§ã³ïŒã¯ããã©ã«ãå€ã§ãã
ãã®ã¢ãããŒãã¯ãæšæºã®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); } }
ãããããã... CommandBindingã®ãããªPropertyBindingãäœæããã€ã³ãã¯ãµãŒãå°ãã ãåçããŸããïŒ
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 = "{store viewModelsïŒMainViewModel}"
ãã€ã³ãã£ã³ã°äžã«ãã³ã³ãããŒã«ãDataContextã ãã§ãªããCommandBindingsã³ã¬ã¯ã·ã§ã³ã«ããã¥ãŒã¢ãã«ããã®å€ãå ¥åããããšããäºå®ã«æ³šç®ããŸãã
ïŒ*ããŒã¯ã¢ããã®ãã¬ãã£ãã¯ã¹ã "{foundationïŒStore viewModelsïŒMainViewModel}"ã®ãããªãã¬ãã£ãã¯ã¹ãæžã蟌ãŸãªãããã«ããããã¯å¥ã®ãããžã§ã¯ãã«å®è£ ããå¿ èŠããããAssemblyInfo.csã®ãããªãã®ãèšè¿°ããå¿ èŠãããåããããžã§ã¯ãã«å®è£ ããå¿ èŠããããŸã
[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 Silverlightã®æ£ç¢ºãªæ¹æ³ã¯ããããŸããããWinPhoneãã©ãããã©ãŒã ã«ã¯ããã€ãã®å¶éããããŸãïŒããŒã¯ã¢ããæ¡åŒµæ©èœãRoutedCommandsãCommandBindingsã¯ãããŸããïŒããæ¬åœã«å¿ èŠãªå Žåã¯ãã€ãã¹ã§ããŸãã ããã«ã€ããŠã¯ã WinPhoneã®èšäºã ãšã¯ã»ã¬ã³ã¹ãžã®é ãã§è©³ãã説æãããŠããŸã ã
PPSäžã§è¿°ã¹ãããã«ã説æãããŠãããã¹ãŠã®æ¹æ³ã¯ãæ¬æ Œçãªããã¹ããšãã£ã¿ãäœæãããšãã«ç§ã«ãã£ãŠé©çšãããŸãã æçµçã«äœæã®ããã«å€æããããšã«èå³ããã人ã¯ã ãã®ãªã³ã¯ãŸãã¯ããã¯ã¢ããã§ãããèŠã€ããããšãã§ããŸãã ããã°ã©ãã³ã°ãšè©©ã«ã¯å€ãã®å ±éç¹ãããããã«æãããŸãïŒèšèã®é人ãæ®éã®äººãè€æ°ã®æ®µèœãåãããšãããã€ãã®ãã¬ãŒãºã§è¡šçŸã§ããããã«ãçµéšè±å¯ãªããã°ã©ããŒã¯æ°è¡ã®ã³ãŒãã§é£ããåé¡ã解決ããŸãã
ããªããžã®ã€ã³ã¹ãã¬ãŒã·ã§ã³ïŒ
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ã³ã¡ã³ãïŒ
-ä»»æã®ã³ã³ãããŒã«ããã¥ãŒãšããŠäœ¿çšã§ããããããã¥ãŒãå¥ã®ãšã³ãã£ãã£ïŒæ°ããã¯ã©ã¹ïŒãšããŠéžæããããããããã£ãå¥ã®ãã¥ãŒã¢ãã«ã«è¿œå ãããããå¿ èŠããªãå ŽåããããŸãã äŸã§èª¬æããŸãã
<Window DataContext={Store viewModels:MainViewModel}> ⊠<!--<TextBlock DataContext={Store viewModels:DetailsViewModel} Text={Binding Name}/>--!> <TextBlock Text={Binding Name, Source={Store viewModels:DetailsViewModel}}/> ⊠</Window>
ã€ãŸããã€ã³ã¿ãŒãã§ã€ã¹ã®ã©ããã«Nameããããã£ã衚瀺ããããã ãã«ãDetailsViewModelãMainViewModelã«æ¿å ¥ããå¿ èŠã¯ãããŸãããããšãã°ãDetailsSââhortViewãäœæããå¿ èŠããããŸããã ãããžã§ã¯ãå ã®ã¯ã©ã¹ã¯å°ãªããæ§é ã¯æ確ã§ãã
-èšäºã§ã¯ãåºæ¬çãªååã瀺ããŸãããããã䜿çšãããšãæ©èœçãªã¢ããªã±ãŒã·ã§ã³ãè¿ éãã€å¹ççã«äœæã§ããŸãã ãã¹ãŠããã®ãŸãŸäœ¿çšããå¿ èŠã¯çµ¶å¯Ÿã«ãããŸãããæ¹åãä¿®æ£ã空æ³ããæš©å©ããããŸãã ãããéçºãæåã§ãïŒ