
WPFãSilverlightãWindowsã¹ãã¢ãããã³Windows Phoneãã©ãããã©ãŒã ã®ã¢ããªã±ãŒã·ã§ã³éçºã«ã¯ãã»ãšãã©ã®å Žåã
MVVMãã¿ãŒã³ã®äœ¿çšãå«ãŸããŸãã ãããã®ãã©ãããã©ãŒã ã®åºæ¬çãªå²åŠã¯ããã¬ãŒã³ããŒã·ã§ã³ïŒãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãšããçšèªã䜿çšããŸãïŒãšæ®ãã®ããã°ã©ã ããžãã¯ãåé¢ããããšã§ãããããããã¯èªç¶ãªããšã§ãã ãã®ã¢ãããŒãã«ã¯ã次ã®å©ç¹ããããŸãã
- ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãšãã¬ãŒã³ããŒã·ã§ã³ããžãã¯ã®åé¢ïŒãã¶ã€ããŒããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã§äœæ¥ã§ããããã«ãããã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ã®æœè±¡ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠããžãã¹ã¢ããªã±ãŒã·ã§ã³ããžãã¯ã§ããã°ã©ããæäœã§ããããã«ããŸãã
- èªåãã¹ãã®é«åºŠãªæ©èœïŒãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãæ®ãã®ããžãã¯ããåé¢ããããšã§ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãä»ãããã¹ãèªååã«ããå¶éãªãã«ãã¬ãŒã³ããŒã·ã§ã³ããžãã¯ãå®å
šã«ãã¹ãã§ããŸãã
- 1ã€ã®ãã¥ãŒã¢ãã«ã«å¯Ÿããè€æ°ã®ãã¥ãŒïŒ1ã€ã®ãã¥ãŒã¢ãã«ã¯ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®å€ãã®å®è£
ã§äœ¿çšã§ããŸãã ããšãã°ãããŒã¿è¡šç€ºã®ççž®ãããå®å
šãªããŒãžã§ã³ããŠãŒã¶ãŒæš©éã«äŸåããã€ã³ã¿ãŒãã§ã€ã¹ã ç°ãªããã©ãããã©ãŒã ã§ãã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ã®åäžã®å®è£
ã䜿çšããæ©èœ
- ã³ã³ããŒãã³ããåå©çšããããã®æ¡åŒµãããæ©äŒïŒãã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ã¯ãã¬ãŒã³ããŒã·ã§ã³ã®å®è£
ãšã¯å¥ã§ããããããããã®äœ¿çšã®ãªãã·ã§ã³ãå¯èœã§ããåºæ¬ã¢ãã«ããã®ç¶æ¿ãããã€ãã®ã¢ãã«ã®æ§æãªã©ã
Windows Phoneãã©ãããã©ãŒã çšã®ã¢ããªã±ãŒã·ã§ã³ãéçºãããšãã«ãã»ãšãã©ã®èšäºãMVVMãã¿ãŒã³ã®åºæ¬çãªå®è£
ã説æããŠãããšããäºå®ã«ééããŸãããããã¯éåžžãã¯ã©ã¹ã®
INotifyPropertyChangedã€ã³ã¿ãŒãã§ã€ã¹ã¢ãã«ã®å®è£
ãåçŽãª
ICommandå®è£
ã®äœæãããã³ãã®ããŒã¿ããã¥ãŒã«ãªã³ã¯ããããã®åçŽãªã¹ã¯ãªããã«
èŠçŽãããŠããŸãã æ®å¿µãªããã䟿å©ãªã€ã³ã¿ãŒãã§ã€ã¹ãåããäžè¬åã¯ã©ã¹ã®å®è£
ãéåæå®è¡äžã®ã¹ã¬ããåæããã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ã®ã¬ãã«ã§ã®ããã²ãŒã·ã§ã³ãªã©ãéèŠãªåé¡ã¯è°è«ã®ç¯å²å€ã§ãã
MVVM Lightã
Prismãªã©ã®ãã¬ãŒã ã¯ãŒã¯ã«æ¬æãè¡šããŠãç§ã¯èªåã®ãããžã§ã¯ãã§ãã®ãã¿ãŒã³ã®ç¬èªã®å®è£
ã䜿çšããããšã奜ã¿ãŸããæãåçŽãªãã¬ãŒã ã¯ãŒã¯ã§ããããã®æ±çšæ§ã®ããã«äžå¿
èŠã«é¢åã ããã§ãã
ãã®èšäºã¯ãWindows Phoneãã©ãããã©ãŒã åãã®ã¢ããªã±ãŒã·ã§ã³éçºã®åºæ¬ã«ç²ŸéããŠããåå¿è
ã察象ãšããŠããŸã.Windows Phoneãã©ãããã©ãŒã åãã®MVVMãã¿ãŒã³ã®å®è£
ãããã«æ·±ãæãäžããããã䜿çšããŠæ§ç¯ãããã¢ããªã±ãŒã·ã§ã³ãå®è£
ããããã®ãããæè»ã§ã·ã³ãã«ãªãœãªã¥ãŒã·ã§ã³ãèŠã€ããŠé©çšããæ¹æ³ãåŠã³ãããšèããŠããŸãã ããããçµéšè±å¯ãªéçºè
ã¯ããã®èšäºãèªåèªèº«ã«ãšã£ãŠèå³æ·±ããã®ã«ãã説æããåé¡ã«å¯Ÿããä»ã®äŸ¿å©ãªè§£æ±ºçãæäŸããã§ãããã
äŸãšããŠãåçŽãªã¢ããªã±ãŒã·ã§ã³ãã¯ã¬ãžããèšç®æ©ããäœæããŸãããã®ãã¹ãŠã®æ©èœã¯åé¢ã³ãŒãã¹ã¿ã€ã«ã§å®è£
ãããŸãã
ã¢ããªã±ãŒã·ã§ã³ã«ã¯2ã€ã®ããŒãžã®ã¿ãå«ãŸããŸããã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ããŒãžã¯ããŒã³ã®ãã©ã¡ãŒã¿ãŒãå
¥åããããã«äœ¿çšãããèšç®ãããããŒã³ã«é¢ãã詳现æ
å ±ããŒãžã¯èšç®ã«é¢ãã詳现æ
å ±ã衚瀺ããããã®ãã®ã§ãã ãã®ãããžã§ã¯ãã®ãœãŒã¹ã³ãŒãã¯ã
github codebehindãã©ã³ãã§å
¥æã§ããŸã
ãã¡ã€ã³ããŒãžMainPage.xamlã®ã¬ã€ã¢ãŠããã¡ã€ã«ã®ãã©ã°ã¡ã³ã
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ScrollViewer> <StackPanel> <StackPanel.Resources> <Style TargetType="TextBlock" BasedOn="{StaticResource PhoneTextNormalStyle}"/> </StackPanel.Resources> <TextBlock Text=" " /> <TextBox x:Name="viewAmount" InputScope="Number" /> <TextBlock Text=" "/> <TextBox x:Name="viewPercent" InputScope="Number" /> <TextBlock Text=" " /> <TextBox x:Name="viewTerm" InputScope="Number"/> <Button x:Name="viewCalculate" Content="" Click="CalculateClick" /> <Border x:Name="viewCalculationPanel" BorderBrush="{StaticResource PhoneBorderBrush}" BorderThickness="{StaticResource PhoneBorderThickness}" Margin="{StaticResource PhoneTouchTargetOverhang}" Visibility="Collapsed"> <StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text=":" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="viewPayment" Style="{StaticResource PhoneTextNormalStyle}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text=":" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="viewTotalPayment" Style="{StaticResource PhoneTextNormalStyle}" /> </StackPanel> <Button Content="" Click="DetailsClick" /> </StackPanel> </Border> </StackPanel> </ScrollViewer> </Grid> <Grid x:Name="viewProgressPanel" Grid.Row="0" Grid.RowSpan="2" Background="{StaticResource OpacityBackgroundBrush}" Visibility="Collapsed"> <ProgressBar Opacity="1" IsIndeterminate="True" /> </Grid>
ãã®ããŒã¯ã¢ããã«ã¯ãããŒã¿ãã€ã³ãã£ã³ã°ãå®å
šã«ãããŸããã ãã¹ãŠã®ããŒã¿ã¯ãåé¢ã³ãŒããã¡ã€ã«ããã³ã³ãããŒã«ã®ããããã£ã«ã¢ã¯ã»ã¹ããŠèšå®ãããŸãã
åé¢ã³ãŒãMainPage.xaml.csã¡ã€ã³ããŒãžãã¡ã€ã«
using System; using System.Threading.Tasks; using System.Windows; using Microsoft.Phone.Controls; namespace MVVM_Article { public partial class MainPage : PhoneApplicationPage { public MainPage() { InitializeComponent(); } private void CalculateClick(object sender, RoutedEventArgs e) { decimal amount; decimal percent; int term; if(!decimal.TryParse(viewAmount.Text, out amount)) { viewProgressPanel.Visibility = Visibility.Collapsed; MessageBox.Show(" "); return; } if(!decimal.TryParse(viewPercent.Text, out percent)) { viewProgressPanel.Visibility = Visibility.Collapsed; MessageBox.Show(" "); return; } if(!int.TryParse(viewTerm.Text, out term)) { viewProgressPanel.Visibility = Visibility.Collapsed; MessageBox.Show(" "); return; } Focus(); viewProgressPanel.Visibility = Visibility.Visible; Task.Run(() => { try { var payment = Calculator.CalculatePayment(amount, percent, term); Dispatcher.BeginInvoke(() => { viewCalculationPanel.Visibility = Visibility.Visible; viewPayment.Text = payment.ToString("N2"); viewTotalPayment.Text = (payment * term).ToString("N2"); }); } finally { Dispatcher.BeginInvoke(() => { viewProgressPanel.Visibility = Visibility.Collapsed; }); } }); } private void DetailsClick(object sender, RoutedEventArgs e) { var pageUri = string.Format("/DetailsPage.xaml?amount={0}&percent={1}&term={2}", viewAmount.Text, viewPercent.Text, viewTerm.Text); NavigationService.Navigate(new Uri(pageUri, UriKind.Relative)); } } }
èšç®ã®äžéšã¯ããã¯ã°ã©ãŠã³ãã¹ããªãŒã ã«è»¢éãããããšã«æ³šæããŠãã ããããã®å Žåããããè¡ãå¿
èŠã¯ãããŸããã ããã¯ãã¹ã¬ããã®åæãã«ããŒããããã®ãã®ã§ãã ã³ã³ãããŒã«ã®ãã¹ãŠã®ããããã£ã¯ãã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ã¹ã¬ããããèšå®ããå¿
èŠããããŸããå¥ã®ã¹ã¬ããããã³ã³ãããŒã«ã®ããããã£ãèšå®ããå Žåã¯ãã³ã³ãããŒã«ãã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ã¹ã¬ããã«è»¢éããå¿
èŠããããŸãã ãããã®ç®çã®ããã«ãããŒãž
Dispatcherãªããžã§ã¯ãã䜿çšãããŸããããã¯ãåžžã«ã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ã¹ã¬ããã«é¢é£ä»ããããŸãã
詳现ãªã¯ã¬ãžããã®èª¬æããŒãžãžã®ãã©ã¡ãŒã¿ãŒã®è»¢éã¯ãããŒãžURIãã©ã¡ãŒã¿ãŒãä»ããŠå®è¡ãããŸãã
ããŒã³ã®è©³çŽ°ããŒãžãåæ§ã®æ¹æ³ã§æ§æãããŠããŸãã æ¯æãã¹ã±ãžã¥ãŒã«è¡šã®èšå
¥ã«æ³šæããŠãã ããããã®ãããã¯ã¯ãItemsControlã䜿çšããŠç°¡åã«å®è£
ã§ããŸããã ãã ãããã®ãããªå®è£
ã§ã¯ããŒã¿ãã€ã³ãã£ã³ã°ã䜿çšããå¿
èŠããããèšäºã®ç®çã«ã¯é©ããŠããŸããã
DetailsPage.xaml.csãã¡ã€ã«ã®æ¯æãã¹ã±ãžã¥ãŒã«è¡šã«èšå
¥ãã
var style = (Style)Resources["PhoneTextNormalStyle"]; foreach(var record in schedule) { var grid = new Grid(); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); var loanElement = new TextBlock { Text = record.Loan.ToString("N2"), Style = style }; Grid.SetColumn(loanElement, 0); var interestElement = new TextBlock { Text = record.Interest.ToString("N2"), Style = style }; Grid.SetColumn(interestElement, 1); var balanceElement = new TextBlock { Text = record.Balance.ToString("N2"), Style = style }; Grid.SetColumn(balanceElement, 2); grid.Children.Add(loanElement); grid.Children.Add(interestElement); grid.Children.Add(balanceElement); viewRecords.Children.Add(grid); }
ã¯ã¬ãžãããèšç®ããããã®ããžãã¯ã¯ãå¥ã®éçã¯ã©ã¹ã®èšç®æ©ã«å®è£
ãããŸãã æ¯æãèšç®æ¹æ³ã®éå§æã®é
延ã«æ³šæããŠãã ããããã®ã¿ã¹ã¯ã¯éäžçãªèšç®ãã·ãã¥ã¬ãŒãããããšã§ãããå®äºãŸã§ã«æéãããããŸãã ã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ã¹ã¬ããã§ãã®ã¡ãœãããåŒã³åºãããšãããšããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ããã³ã°ããŸãã ãããé²ãã«ã¯ããªãœãŒã¹ã倧éã«æ¶è²»ãããã¹ãŠã®ã¿ã¹ã¯ãããã¯ã°ã©ãŠã³ãã¹ã¬ããã§å®è¡ããå¿
èŠããããŸãã
ãã¡ã€ã«Calculator.csã®ãã©ã°ã¡ã³ã
internal static class Calculator { public static decimal CalculatePayment(decimal amount, decimal percent, int term) { Task.Delay(1000).Wait(); percent /= 1200; var common = (decimal) Math.Pow((double) (1 + percent), term); var multiplier = percent*common/(common - 1); var payment = amount*multiplier; return payment; } public static List<PaymentsScheduleRecord> GetPaymentsSchedule(decimal amount, decimal percent, int term) { var balance = amount; var interestRate = percent / 1200; var payment = CalculatePayment(amount, percent, term); var schedule = new List<PaymentsScheduleRecord>(); for (var period = 0; period < term; period++) { var interest = Math.Round(balance * interestRate, 2); var loan = payment - interest; balance -= loan; var record = new PaymentsScheduleRecord { Interest = interest, Loan = loan, Balance = balance }; schedule.Add(record); } return schedule; } }
MVVMã®æãåçŽãªå®è£
次ã«ãMVVMã®æãåçŽãªããŒãžã§ã³ãå®è£
ããŸãããã®ãããåããŒãžã®ãã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ãäœæãããªããžã§ã¯ãã®ããããã£ã®å€æŽã«ã€ããŠãã¥ãŒã«éç¥ããããã«äœ¿çšããã
INotifyPropertyChangedã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŸãã ãœãŒã¹ã³ãŒãã¯ã
githubã®naivemvvmãã©ã³ãã§å
¥æã§ããŸãã
ã¯ã©ã¹ã«ããã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£
ã«ã¯ããªããžã§ã¯ãã®ããããã£ã®å€ãå€æŽããããã³ã«
PropertyChangedã€ãã³ããçæãããããšãå«ãŸããŸãã ãã®åäœã«ãããããŒã¿ãã€ã³ãã£ã³ã°ã¯ãªããžã§ã¯ãã®ç¶æ
ã远跡ããé¢é£ä»ããããããããã£ã®å€ãå€æŽããããšãã«ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ããŒã¿ãæŽæ°ã§ããŸãã
MainPageViewModel.csãã¡ã€ã«ã®ãã©ã°ã¡ã³ã
public class MainPageViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } }
CallerMemberNameå±æ§ã®äœ¿çšã«æ³šæããŠ
ãã ãã ããã®å±æ§ã¯ãã¡ãœãããåŒã³åºãããã¯ã©ã¹ã¡ã³ããŒã®ååããã®ãã©ã¡ãŒã¿ãŒã«æž¡ãå¿
èŠãããããšãã³ã³ãã€ã©ãŒã«äŒããŸãã ããã«ãããã¡ãœãããããããã£èªäœããåŒã³åºãããå Žåãããããã£åãã¡ãœããã«æ瀺çã«æž¡ãããšãã§ããªããªããŸãã
è¡šçŸã¢ãã«ããããã£ã®å®è£
äŸ
private string _amount; public string Amount { get { return _amount; } set { _amount = value; OnPropertyChanged(); } }
ãã£ãŒã«ãå€ãèšå®ããåŸãOnPropertyChangedã¡ãœãããåŒã³åºãããåŒã³åºãããããããã£ã®å€ã®å€æŽã«é¢ããã€ãã³ããçæããŸãã
ãã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ã¯ããã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ã«åºæã®ã¢ã¯ã·ã§ã³ãå®è¡ã§ããã³ãã³ããã³ã³ã·ã¥ãŒãã«æäŸã§ããŸãã ã³ãã³ãã¯ICommandã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ãããªããžã§ã¯ãã§ã;ã³ã³ã·ã¥ãŒããŒãã³ãã³ãã§æå®ãããã¢ã¯ã·ã§ã³ãå®è¡ããå¿
èŠãããå ŽåããŠãŒã¶ãŒã¯ã³ãã³ãã®Executeã¡ãœãããåŒã³åºãå¿
èŠããããŸãã ããŒã ã¯ãæ¶è²»è
ã«ãããå®äºã§ãããã©ããã«é¢ããæ
å ±ãæäŸããŸãã ã³ãã³ãã®å¯çšæ§ã«é¢ããæ
å ±ãååŸããã«ã¯ãCanExecuteã¡ãœãããåŒã³åºããCanExecuteChangedã€ãã³ãã«ãµãã¹ã¯ã©ã€ãããå¿
èŠããããŸããCanExecuteChangedã€ãã³ãã¯ãã³ãã³ãã®ç¶æ
ã®å€åã«ã€ããŠã³ã³ã·ã¥ãŒããŒã«éç¥ããŸãã
ãã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ã®åã
ã®ã¢ã¯ã·ã§ã³ã«å¯Ÿããã³ãã³ãã®å®è£
ã¯éåžžã«æéã®ãããããã»ã¹ã§ããããã容æã«ããããã«ãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã®äœææã«æå®ãããããªã²ãŒãã«ã³ãã³ãã¡ãœããã®å®è¡ãå§ä»»ããã¯ã©ã¹DelegateCommandãäœæããŸã
DelegateCommand.csãã¡ã€ã«
public sealed class DelegateCommand : ICommand { private readonly Action<object> _execute; private readonly Func<object, bool> _canExecute; public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null) { if(execute == null) { throw new ArgumentNullException(); } _execute = execute; _canExecute = canExecute; } public bool CanExecute(object parameter) { return _canExecute == null || _canExecute(parameter); } public void Execute(object parameter) { if(!CanExecute(parameter)) { return; } _execute(parameter); } public event EventHandler CanExecuteChanged; public void RiseCanExecuteChanged() { var handler = CanExecuteChanged; if(handler != null) { handler(this, EventArgs.Empty); } } }
DelegateCommandã¯ã©ã¹ã䜿çšãããã¥ãŒã¢ãã«ã³ãã³ãã®å®£èš
private DelegateCommand _calculateCommand; public DelegateCommand CalculateCommand { get { if(_calculateCommand == null) { _calculateCommand = new DelegateCommand(o => Calculate()); } return _calculateCommand; } }
ãã¥ãŒã¢ãã«ãäœæãããããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®èª¬æãå€æŽããŸãã ãããè¡ãã«ã¯ãMainPage.xaml.csãã¡ã€ã«ãããã¹ãŠã®ã³ãŒããåé€ããããŒãžã³ã³ã¹ãã©ã¯ã¿ãŒã§ããŒãžã®DataContextããããã£ã®å€ãèšå®ããŸãããã®åŸãããŒã¿ãã€ã³ãã£ã³ã°ã䜿çšã§ããŸãã
å€æŽåŸã®MainPage.xaml.csãã¡ã€ã«
using Microsoft.Phone.Controls; using MVVM_Article.ViewModels; namespace MVVM_Article { public partial class MainPage : PhoneApplicationPage { public MainPage() { InitializeComponent(); DataContext = new MainPageViewModel(); } } }
ããŒãžã®ã³ãŒãããã€ã³ãã¯1è¡ã«åæžãããŠããããšã«æ³šæããŠãã ããã以éã®ç« ã§ã¯ããã®è¡ãåé€ãããŸãã
次ã«ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®èª¬æã§ããŒã¿ãã€ã³ãã£ã³ã°ãèšå®ããå¿
èŠããããŸãã {Binding Path = <Property Name>}ã³ã³ã¹ãã©ã¯ãã¯ãããŒã¿ãã€ã³ãã£ã³ã°ãæå®ããããã«äœ¿çšãããŸã;ã»ãšãã©ã®å ŽåãPathã¯çç¥ã§ãã{Binding <Property Name>}ã«çž®å°ã§ããŸãã
MainPage.xamlãã¡ã€ã«ã®ãã©ã°ã¡ã³ãã§ããããŒã¿ãã€ã³ãã£ã³ã°ã®äŸ
<TextBlock Text=" " /> <TextBox Text="{Binding Term, Mode=TwoWay}" InputScope="Number"/> <Button Content="" Command="{Binding CalculateCommand}" /> <Border BorderBrush="{StaticResource PhoneBorderBrush}" BorderThickness="{StaticResource PhoneBorderThickness}" Margin="{StaticResource PhoneTouchTargetOverhang}" Visibility="{Binding IsCalculated, Converter={StaticResource BoolToVisibilityConverter}}">
ããã¹ããã£ãŒã«ãã®ãã€ã³ãã£ã³ã°ãèšå®ãããšãã¯ãMode = TwoWayãã©ã¡ãŒã¿ãŒã«æ³šæããŠãã ããããã®ãã©ã¡ãŒã¿ãŒã¯ãã³ã³ãããŒã«ã®ããããã£ã®å€ãå€æŽãããšãã«ãã¥ãŒã¢ãã«ãã£ãŒã«ãã«æž¡ãå¿
èŠãããããŒã¿ãã€ã³ãã£ã³ã°ã瀺ããŸãã ãã®ããã«ããŠããã¥ãŒã¢ãã«ã¯ãŠãŒã¶ãŒå
¥åããŒã¿ãåãåããŸãã ã³ã³ãããŒã«ã®Visibilityããããã£ãšIsLoadedãã¥ãŒã¢ãã«ã¯ãã¿ã€ããç°ãªããããçŽæ¥æ¥ç¶ã§ããŸããã ãã®ãããªåé¡ã解決ããããã«ãå€ã³ã³ããŒã¿ãŒãæå³ãããŠããŸãã
ããŒã«åã®ããããã£ãVisibilityåã®ããããã£ã«ãã€ã³ãããã«ã¯ãã³ã³ããŒã¿ãŒBoolToVisibilityConverterãäœæããŸã
public class BoolToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (value as bool?) == true ? Visibility.Visible : Visibility.Collapsed; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
ãã®ã³ã³ããŒã¿ãŒã䜿çšãããšãããŒã«åãšå¯èŠæ§ã®ãã£ãŒã«ããçžäºã«ãã€ã³ãã§ããŸãã
Visibility="{Binding IsCalculated, Converter={StaticResource BoolToVisibilityConverter}}"
æ®å¿µãªãããDeptailsPageããŒãžã®MVVMãã¿ãŒã³ãå®è£
ããå Žåãã¡ã€ã³ããŒãžããæž¡ããããã©ã¡ãŒã¿ãŒã§ãã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ãåæåããããã«äœ¿çšããããããåé¢ã³ãŒããå®å
šã«åãé€ãããšã¯ã§ããŸããã§ããã
ãããã«
çŸåšã®ã¢ããªã±ãŒã·ã§ã³ã¯ãæ£åŒã«ã¯MVVMãã¿ãŒã³ã«æºæ ããŠããŸãããå®éã«ã¯ãã³ãŒãããã€ã³ããããŒãžã¯ã©ã¹ããå¥ã®ã¯ã©ã¹ã«ç§»åããã ãã§ãã å®è£
ã«ã¯å€ãã®æ¬ ç¹ããããèšäºã®åé ã§èª¬æããMVVMã®å©ç¹ã䜿çšã§ããŸããã
次ã®èšäºã§ã¯ãMVVMã§ã®DIã®äœ¿çšãããã²ãŒã·ã§ã³ã®å®è£
ããŠãŒã¶ãŒæäœãMVVMåºæ¬ã¯ã©ã¹ã®äžè¬åãªã©ã®ãããã¯ãæ±ããŸãã