ã¢ããªã±ãŒã·ã§ã³ã®çš®é¡ã®éžæã¯ãåžå Žã§æåã«è³Œå ¥ããããã°ã©ã ãäºç®ã ãã ã£ããšããäºå®ã«ãããã®ã§ããããã®èšç»ã¯ãªããããã€ãã®æçšãªæ©èœïŒSkyDriveãžã®èªåããã¯ã¢ãããªã©ïŒããããŸãã
éçºåå
æ©èœã¯10ã14æ¥éç¶ãå°ããªå埩ã§åŸã ã«å¢å ãããã®ãã¡3ã5æ¥éã¯åã®ããŒãžã§ã³ã§ã®å®è¡ã«ã1æ¥éã¯ãã¬ã€ã³ã¹ããŒãã³ã°ã«ãæ®ãã¯èšç»ã®å®è£ ããã¹ããããã³èšäºã®èšèšã«å²ãåœãŠãããŸãã
åæ§ã®ãŠãŒãã£ãªãã£ã®ä»£ããã«ãäœæããã¢ããªã±ãŒã·ã§ã³ãæ¯æ¥äœ¿çšããäºå®ãªã®ã§ãæ©èœã¯æ£ç¢ºã«å¿ èŠãªãã®ã§ãªããã°ãªãããæžãã®ãç°¡åãªãã®ã§ã¯ãããŸããã
æåã®å埩ïŒèšç»
ãŸãããã©ã³ã¶ã¯ã·ã§ã³ãè¿œå ããå°ãªããšãåºæ¬çãªã«ããŽãªãäœæããå¿ èŠããããŸããããããªããšã䜿çšã®1é±éã§å°ããªãŽãç®±ãã§ããŠããŸããŸãã
ãã®èšäºã§ã¯ãããŒã¿ããŒã¹ã®äœæããã»ã¹ãšã«ããŽãªã®è¿œå ããã»ã¹ã詳现ã«ïŒããããå€ãããïŒèŠãŠãããŸãã ãã©ã³ã¶ã¯ã·ã§ã³ãè¿œå ããããã»ã¹ã¯ãã«ããŽãªã®æäœãšã»ãŒ100ïŒ é¡äŒŒããŠããããã®èæ ®ãèšäºãéåžžã«å€§ããªãµã€ãºã«èšããŸãããããèæ ®ããŸããã ãŸããã«ããŽãªãç·šéããããã»ã¹ã¯èæ ®ããŸãããã䜿çšããäœæ¥ã®ã¢ãã«ãèãããšã+-10åããããŸãã
å¿ èŠã«å¿ããŠããããã®ãããã¯ã¯æ¬¡ã®èšäºã§ç°¡åã«èª¬æããããã¹ãããã§ããŸãã
ãããã£ãŠã次ã®ãããªè³ªåãæ€èšããŸãã
- WP7éçºã®åºç€
-
Metroã®åºæ¬[1] - SQLCEããŒã¿ããŒã¹ãæäœããã³ãŒããã¡ãŒã¹ãã®ååã«åºã¥ããŠã¢ãã«ãäœæãã
åææ¡ä»¶
- .NETããã³CïŒã®åºæ¬çãªç¥è
- Windows Phone SDK 7.1
- Silverlight for Windows PhoneããŒã«ããã ïŒ 2011幎11æçïŒ
- ãã³ãŽãŒçšã«æŽæ°ãããPrism for Phone [2]
éçºïŒããŒã¿ããŒã¹ã®äœæ
誰ãããã®èšäºãã¬ãã¹ã³ãšããŠäœ¿çšãããå Žåã¯ãè«ççã«å®äºããéèŠåºŠã®é«ã段éããšã«ãçµæãå«ãã¢ãŒã«ã€ããžã®ãªã³ã¯ã衚瀺ãããŸãã SkyDriveã®ãã¹ãŠã®ãœãŒã¹ ã åæžã®å Žåãåå¥ã®ãã¡ã€ã«ãpastebinã«è¡šç€ºãããŸã ã
ã¢ããªã±ãŒã·ã§ã³ã®æ§é ãéžæãããšããç§ã¯äž»ã«ãããžã§ã¯ãã«ãã£ãŠå®è¡ãããæ©èœã®è«ççãªåé¢ã«çŠç¹ãåãããŸãã ãããã®èæ ®äºé ã«åºã¥ããŠãããŒã¿ããŒã¹ãšãã¹ãŠã®çš®é¡ã®ããŒã¿ã®èª¬æãäœæããããã«ããšã³ãã£ãã£ãšåŒã°ããå¥ã®ãããžã§ã¯ããäœæããŸããSystem.Data.Linqããã³Microsoft.Practices.PrismãReferencesã«è¿œå ããããšãå¿ããªãã§ãã ããã 解決çã¯ãã¡ã ã
ããã«äºçŽãè¡ããŸã-ãã©ã³ã¶ã¯ã·ã§ã³ã®æŠå¿µã«ãããããŒã¿ããŒã¹å ã®ãã©ã³ã¶ã¯ã·ã§ã³ã§ã¯ãªããéèãã©ã³ã¶ã¯ã·ã§ã³ãæå³ããŸãã
ããŒã¿ããŒã¹ãäœæãããšãã¯ãã³ãŒããã¡ãŒã¹ãã¢ãããŒã[3]ã䜿çšããŸãä»æ¥ã®ã¿ã¹ã¯ã§ã¯ããã©ã³ã¶ã¯ã·ã§ã³ãšã«ããŽãªãšãã2ã€ã®ããŒãã«å šäœã«æºè¶³ããŠããŸãã 2ã€ã®ç©ºã®ããŒãã«ãäœæããããããããŒã¿ããŒã¹ã«è¿œå ããŸãã
Transaction.cs
[Table(Name = "Transactions")] public class Transaction : NotificationObject
Category.cs
[Table(Name = "Categories")] public class Category : NotificationObject
Database.cs
public class Database : DataContext { private static string DBConnectionString = "Data Source=isostore:/Database.sdf"; public Database() : base(Database.DBConnectionString) { this.DeferredLoadingEnabled = true; } public Table<Bick.Budget.Entities.Categories.Category> Categories; public Table<Bick.Budget.Entities.Transactions.Transaction> Transactions; }
ãã£ãŒã«ãã§ã¯ãªããããŒã¿ããŒã¹ããããã£ã«ããŒãã«ãäœæããããšããèããªãã§ãã ããã ããããã£ãäžè¬åãã«äœ¿çšãããšããæäœçãªç¿æ
£ã®ãããããŒã¿ããŒã¹ããŸã£ããæ©èœããªãçç±ãç解ããããšããŠçŽ1æé殺ããŸããã
ããã§ããã©ã³ã¶ã¯ã·ã§ã³ãšã«ããŽãªã¯ãå°æ¥ã®UIãšã®éåžžã®å¯Ÿè©±ã®ããã«Prismã§å®çŸ©ãããNotificationObjectãç¶æ¿ããŸãã ãšããã§ãéçºæã«ã¯MVVMãã¿ãŒã³ã䜿çšããŸãã
ããŒã¿ããŒã¹ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãDefferedLoadingEnabledãã©ã°ãèšå®ããŠãããŒã¿ããŒã¹ããã®é¢é£ãªããžã§ã¯ãã®èªåèªã¿èŸŒã¿ãç¡å¹ã«ããŸãã å¿ èŠã«ãªããŸã-å¥éæå®ããŸãã
ããŒãã«ã®å 容ã®åœ¢æã«é²ã¿ãŸãã ãã®çµæã次ã®ããã«ãªããŸãã
Transaction.csã®ãã€ã©ã€ã ïŒ
[Column(IsPrimaryKey = true)] public Guid ID { ... } ... private EntityRef<Categories.Category> category; [Association(Name = "FK_Transactions_Category", Storage = "category", ThisKey = "CategoryID", IsForeignKey = true)] public Categories.Category Category { get { return this.category.Entity; } set { Categories.Category previousValue = this.category.Entity; if (((previousValue != value) || (this.category.HasLoadedOrAssignedValue == false))) { if ((previousValue != null)) { this.category.Entity = null; previousValue.Transactions.Remove(this); } this.category.Entity = value; if ((value != null)) { if ((value.AddedTransactions == null) || (!value.AddedTransactions.Contains(this))) { value.Transactions.Add(this); } this.CategoryID = value.ID; } else { this.category = new EntityRef<Categories.Category>(); } this.RaisePropertyChanged(() => this.Category); } } }
IDãã©ã¡ãŒã¿ãŒã¯ãããŒãã«åãšäž»ããŒã§ãã æ®ãã®åãColumnå±æ§ã§æå®ãããŸãã msdnã®å±æ§ããŒã¹ã®ãããã³ã°ã®è©³çŽ°ãèªãããšãã§ããŸãã
CategoryãšCategoryIDã¯ããã©ã³ã¶ã¯ã·ã§ã³ãã«ããŽãªã«ãã€ã³ããã圹å²ãæãããŸãããã®äŸã§ã¯ãå€éšããŒFK_Transactions_CategoryãäœæããŸããã è¥å€§åããã»ãã¿ãŒã®çç±ã¯ããã©ã³ã¶ã¯ã·ã§ã³ã芪ã«ããŽãªã«å²ãåœãŠããšãã«ã以åã®èŠªã«ããŽãªãããã©ã³ã¶ã¯ã·ã§ã³ãåé€ããæ°ãããã©ã³ã¶ã¯ã·ã§ã³ã«è¿œå ããå¿ èŠãããããã§ãã 倧ãŸãã«èšãã°-EFã®ããã²ãŒã·ã§ã³ããããã£ã ã«ããŽãªã¯ããããå®è£ ããããã«æå°éã®ã³ãŒãã䜿çšããŸãã
Category.cs ïŒ
public EntitySet<Transactions.Transaction> Transactions { get { if (this.transactions == null) { this.transactions = new EntitySet<Transactions.Transaction>(); this.transactions.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(this.OnTransactionsChanged); } return this.transactions; } ... } ... private void OnTransactionsChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { this.AddedTransactions = e.NewItems; foreach (Transactions.Transaction t in e.NewItems) { t.Category = this; } this.AddedTransactions = null; this.RaisePropertyChanged(() => this.Transactions); }
å®éãCategoryã§ã¯ãã«ããŽãªããã©ã³ã¶ã¯ã·ã§ã³ã«å²ãåœãŠãããŠããªãããæ°ããèŠçŽ ãã«ããŽãªå
ã®ãã©ã³ã¶ã¯ã·ã§ã³ã®ãªã¹ãã«è¿œå ãããç¶æ³ããã£ããããŸãã
ããŒã¹ã®æºåãã§ããŸããã SkyDriveã®ãœãªã¥ãŒã·ã§ã³ ã
éçºïŒUIãäœæãã
Windows Phoneã¢ããªã±ãŒã·ã§ã³ãšããŠäœæããã·ã§ã«ãããžã§ã¯ããã€ãŸãããã®æ®µéã§ã¯ããããã/ããã©ããªã©ã®ã³ã³ãããŒã«ã¯äœ¿çšããŸããã ã¢ããªã±ãŒã·ã§ã³ãšã®ãŠãŒã¶ãŒã®å¯Ÿè©±ã¯ããããã次ã®ã¹ããŒã ã«åŸã£ãŠè¡ãããŸãã
äœæããããã«ãExpression BlendãšSketchFlowïŒç¡æSDKã«ã¯å«ãŸããŠããŸããïŒããã³WP7ã®ã¹ã±ãããããŒãã³ãã¬ãŒãïŒ CodePlex ïŒã䜿çšããŸãã
ãããã®ç»é¢ã次ã®ãã¥ãŒã«åå²ããŸããæ°èŠ/ãã©ã³ã¶ã¯ã·ã§ã³ã®ç·šéãã«ããŽãªã®æ°èŠ/ç·šéãã«ããŽãªãªã¹ãããã©ã³ã¶ã¯ã·ã§ã³ãªã¹ãããã©ã³ã¶ã¯ã·ã§ã³ã®åŠçãæ åœããéšåã¯å¥ã®ãããžã§ã¯ãã«è»¢éãããŸãã SkyDriveã®ãœãªã¥ãŒã·ã§ã³ ã
ãŸããã«ããŽãªã®ãªã¹ãã衚瀺ããã«ããŽãªãè¿œå ããæ©èœãå®è£ ããå¿ èŠããããŸãã ããã«ã€ããŠç¹å¥ãªããšã¯äœããããŸããããããã©ãŒãã³ã¹ã«çŠç¹ãåãããããšããŠãããããããŒã¿ããŒã¹ãå°ãæ¹è¯ããå¿ èŠããããŸãã å®éã®ãšãããã«ããŽãªã®ãªã¹ãã衚瀺ãããšãã«ã¯äœãç·šéããŸãããã§ããã ãæ©ãã«ããŽãªã®ãªã¹ããååŸããã ãã§ãã ãããè¡ãããã«ã Database.csã§ãã®ãããªä¿®æ£ãè¡ããŸã ã
public Database(bool isReadOnly = false) : base(Database.DBConnectionString) { if (!this.DatabaseExists()) { this.CreateDatabase(); } this.DeferredLoadingEnabled = true; this.ObjectTrackingEnabled = !isReadOnly; }
ãããã£ãŠãisReadOnly == trueã®å Žåãã³ã³ããã¹ããªããžã§ã¯ãã®å€æŽã®è¿œè·¡ããªãã«ããŸããããã«ãããåçŽãªèªã¿åãã®é床ãå¹³åã§10å以äžåäžããŸãã
UIãäœæãããšããç§ãã¡ãçŽé¢ããŠããåé¡ã®1ã€ã¯ãä»»æã®BehaviorãApplicationBarButtonã«ã¢ã¿ããã§ããªãããšã§ãïŒã³ãã³ãã«ãã€ã³ãããããã«ãããå¿ èŠã§ãïŒã Prism.Interactionsã«ã¯DependencyProperty ApplicationBarButtonCommandããããŸãããäœããã®çç±ã§æ©èœããŸããã§ããã ãããã£ãŠãéåžžã«äŸ¿å©ãªAppBarUtilsã©ã€ãã©ãªã䜿çšããå¿ èŠããããŸããã
CategoriesView.xamlããã®èå³æ·±ãç¬é ïŒ
<phone:PhoneApplicationPage xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:appbar="clr-namespace:AppBarUtils;assembly=AppBarUtils"> ⊠<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False" Mode="Default"> <shell:ApplicationBarIconButton IconUri="/icons/appbar.add.rest.png" Text="add new"/> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar> <i:Interaction.Behaviors> <appbar:AppBarItemCommand Id="add new" Command="{Binding Path=AddCategoryCommand}"/> </i:Interaction.Behaviors>
ã»ãšãã©ã®å Žåããã¿ã³ã®ã¢ã¯ã·ã§ã³ã¯ã¢ããªã±ãŒã·ã§ã³ã®ä»ã®ããŒãžãžã®é·ç§»ã§ãããViewModelããã®ããã²ãŒã·ã§ã³ãæäœããããã®äŸ¿å©ãªã¡ã«ããºã ãäœæããå¿
èŠããããŸãã 䟿å©ã§æ¯èŒç銎æã¿ã®ããïŒç§ã¯ãã€ãŠãã¹ã¯ãããMVVMãåæ§ã®æ¹æ³ã§äœ¿çšããŠããŸããïŒããã®æ¹æ³ãããã§èª¬æããŸã ã ApplicationControllerã¯ã©ã¹ãäœæããŠãCommonãããžã§ã¯ãã«åæ§ã®ååãå®è£
ããŸãã ãŸãããã¹ãŠã®ãã¥ãŒã¯ãKnownPageséçã¯ã©ã¹ã§å®çŸ©ãããŸãã
public static class KnownPages { public const string AddCategory = "/Views/CategoryAddEditView.xaml?mode=Add"; public const string EditCategory = "/Views/CategoryAddEditView.xaml?mode=Edit&id={0}"; public const string ListCategories = "/Views/CategoriesView.xaml"; public const string CategoryDetails = "/Views/CategoryDetailsView.xaml?id={0}"; }
ãApplicationControllerããã®NavigateToïŒïŒïŒå
ã®ãã®ã¯ããŸãæ®ã£ãŠããŸããïŒã¯æ¬¡ã®ããã«ãªããŸãã
public void NavigateTo(string url, params object[] data) { Uri address = new Uri(String.Format(url, data), UriKind.Relative); PhoneApplicationFrame root = Application.Current.RootVisual as PhoneApplicationFrame; root.Navigate(address); }
ããã§ããã©ã¡ãŒã¿mode = AddãAddEditããŒãžã«æž¡ããããViewModelã§ããã²ãŒã·ã§ã³ã€ãã³ãããã£ããããæååããããŒã¿ãååŸããå¿
èŠããããŸãã æ®å¿µãªãããçŸæç¹ã§ã¯ãCodeBehind'eã§OnNavigatedToã¡ãœããããªãŒããŒã©ã€ãããViewModelã§å¯Ÿå¿ããã¡ãœãããåŒã³åºããªãã·ã§ã³ã決å®ããŸããã
CategoryAddEditView.xaml.cs ïŒ
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e); ((CategoryAddEditViewModel)this.DataContext).OnNavigatedTo(this.NavigationContext, this.NavigationService.BackStack.First()); }
ã³ãŒããããããããã«ãããã²ãŒã·ã§ã³ã³ã³ããã¹ãïŒããŒãžã¢ãã¬ã¹ãããã©ã¡ãŒã¿ãŒãåŒãåºãã®ã«äŸ¿å©ãªå ŽæïŒã ãã§ãªããçŸåšã®ããŒãžã«åãæ¿ããããŒãžãéä¿¡ããŸãã
次ã«ãã«ããŽãªãè¿œå ããããã»ã¹ãå®è£ ããçªã§ãã ãã¬ãŒã³ãã¥ãŒãšãã¬ãŒã³ãã¥ãŒã¢ãã«ã ãããã2ã€ãããŸãã ãŸããã¢ãŒããã©ã¡ãŒã¿ãŒãååŸããŠåŠçããNavigationContextãããããããåãMV-VMãã«ããŽãªã®ç·šéã«äœ¿çšããŸãïŒå®¿é¡ã«ãªããŸãïŒã 2çªç®ã¯ãTextBoxã®WP7ã§ã¯ãèŠçŽ ããã©ãŒã«ã¹ã倱ã£ããšãã«ã®ã¿ããããã£å€ã®å€æŽãçºçããããšã§ãã ãã€ãã£ãã®æ¹æ³ã§ã¯ãããã¯å®è£ ãããŠããªããããPrismïŒCategoryAddEditView.xamlãã¡ã€ã«ïŒã䜿çšããŸãã
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Interactivity;assembly=Microsoft.Practices.Prism.Interactivity" ... <TextBox TextWrapping="Wrap" Text="{Binding Path=Category.Name, Mode=TwoWay}"> <i:Interaction.Behaviors> <prism:UpdateTextBindingOnPropertyChanged /> </i:Interaction.Behaviors> </TextBox>
ã«ããŽãªãä¿åããããã»ã¹ã¯æ¬¡ã®ããã«ãªããŸãã
CategoryAddEditViewMode.cs
public void SaveCategory() { if (!this.isEditMode) { this.model.AddCategory(this.Category); ApplicationController.Default.GoBack(); } }
泚æãã¹ãç¹-CategoriesViewããŒãžã«ã¯ç§»åãããåã®ããŒãžã«æ»ããŸãã ãŠãŒã¶ãŒã[æ»ã]ãã¿ã³ãã¯ãªãã¯ããåŸãæåŸ
ããå Žæã§éæ¹ã«æ®ããŠããªãããã«ãã¢ããªã±ãŒã·ã§ã³å
ã®ãã®ãããªé·ç§»ã«æ³šæãã䟡å€ããããŸãã
CategoryAddEditModel.csã§ã¯ãä¿åã¯æ¬¡ã®ããã«ãªããŸãã
public void AddCategory(Category cat) { using (Database db = new Database()) { db.Categories.InsertOnSubmit(cat); db.SubmitChanges(); } }
ãã§ãã¯ãšæ€èšŒã¯è¡ãããŠããªãããšãããããŸãããããã¯æªãããšã§ãã ããããæåã®èšäºã§ã¯æ¢ã«ããªãã®éã®è³æããããŸãããä»ã§ã¯äž»èŠãªæ©èœãçµäºããŠããã°ã©ã ã®äœ¿çšãéå§ããããšãããéèŠã§ã-èšäºéãŸãã¯ä»¥äžã§æ®ããè¡ããŸãã
ã«ããŽãªã®ãªã¹ãã«æ»ããšããViewãšViewModelã¯åå²ãåœãŠãããªãããããªã¹ãããŒãžããè¿œå ããŒãžã«åãæ¿ãããšããIsReloadPendingãã©ã°ãèšå®ãããããåŠçããŠãæ»ãæã«ãªã»ããããŸãã
CategoriesViewModel.cs ïŒ
private void AddCategory() { this.isReloadPending = true; ApplicationController.Default.NavigateTo(KnownPages.AddCategory); } public void OnNavigatedTo(NavigationContext context, JournalEntry lastPage) { if (this.isReloadPending) { this.isReloadPending = false; this.Categories = this.model.GetCategoriesList(); } }
ãŸãšã
ä»æ¥ãWP7ã§ã®äœæ¥ã«å¿ èŠãªãã¹ãŠã®ããŒã«ãå ¥æããããŒã¿ããŒã¹ã§ã®åäœããã¹ãããWindows Phoneã®ããã°ã©ã ãšåŠç¿ããã°ã©ãã³ã°ãã¯ãããžã®ãããªãéçºã®æºåãæŽããŸããã ãŸããããã€ãã®åŠšå®³ïŒApplicationBarãTextBoxïŒã«ééããããããå æããŸãããã¯ã-ããã°ã©ã ã䜿çšããæºåãã§ããŠããŸããã§ããïŒããŒã¿ã³ã¬ã¯ã¿ãŒãšããŠïŒãããã®æ®µéããçŽ1ã2æéããããŸãã 誰ãæ°ã«ãã-圌ãã¯èªåã§ãããè©ŠããŠã¿ãŸãã SkyDriveã®ãœãªã¥ãŒã·ã§ã³ ã
åæã«ãCïŒã«ç²ŸéããŠãã人ã¯ãMicrosoftã®ã¢ãã€ã«ãã©ãããã©ãŒã ã¯éåžžã«ç°¡åã«ç¿åŸã§ããç¬ç«ããŠç°¡åã«ç¿åŸã§ããããšãç解ããŠããã¯ãã§ãã
åæã«ãåæ§ã®èšäºãæžãã®ã«æéããããããšã«æ°ä»ããŸããã ãã®èšäºã¯ãã¢ããªã±ãŒã·ã§ã³ã®äœæãšäžŠè¡ããŠãæ¥èšåœ¢åŒã§äœæãããŸããã
ä»åŸã®èšç»
次ã®èšäºã§ã¯ãæ€èšããããšæããŸãã- äºæ¬¡ã¿ã€ã«äœæããã»ã¹
- ã¢ããªã±ãŒã·ã§ã³èµ·åã®æé©å
- SketchFlowã§ã®ã¢ããªã±ãŒã·ã§ã³ã®ãããã¿ã€ãã³ã°