1

そのため、私はWindows Phone用のMVVMパターンを学習している途中で、ViewをViewModelにバインドする方法に固執しました。現在作成しているアプリは、現在および次の5日間の天気を取得し、UserControlを使用してMainPage.xamlのパノラマアイテムの1つに表示します。

Forecasts.ItemsSource=forecast;を単純に設定することはできません。私のWeatherViewModelでは、Forecast(WeatherViewのリストボックス要素名)が現在のコンテキストに存在しないと表示されます。

誰かがそれをバインドする方法を教えてもらえますか?そして、誰かがWindows-Phoneのmvvmパターンの良いソース/サンプルサンプルを持っていますか?前に感謝します。

編集:

WeatherModel.cs

namespace JendelaBogor.Models
{
    public class WeatherModel
    {
        public string Date { get; set; }
        public string ObservationTime { get; set; }
        public string WeatherIconURL { get; set; }
        public string Temperature { get; set; }
        public string TempMaxC { get; set; }
        public string TempMinC { get; set; }
        public string Humidity { get; set; }
        public string WindSpeedKmph { get; set; }
    }
}

WeatherViewModel.cs

namespace JendelaBogor.ViewModels
{
    public class WeatherViewModel : ViewModelBase
    {
        private string weatherURL = "http://free.worldweatheronline.com/feed/weather.ashx?q=";
        private const string City = "Bogor,Indonesia";
        private const string APIKey = "APIKEY";

        private IList<WeatherModel> _forecasts;
        public IList<WeatherModel> Forecasts
        {
            get 
            {
                if (_forecasts == null)
                {
                    _forecasts = new List<WeatherModel>();
                }

                return _forecasts;
            }

            private set
            {
                _forecasts = value;

                if (value != _forecasts)
                {
                    _forecasts = value;
                    this.NotifyPropertyChanged("Forecasts");
                }
            }
        }

        public WeatherViewModel()
        {
            WebClient downloader = new WebClient();
            Uri uri = new Uri(weatherURL + City + "&num_of_days=5&extra=localObsTime&format=xml&key=" + APIKey, UriKind.Absolute);
            downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ForecastDownloaded);
            downloader.DownloadStringAsync(uri);
        }

        private void ForecastDownloaded(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Result == null || e.Error != null)
            {
                MessageBox.Show("Cannot load Weather Forecast!");
            }

            else
            {
                XDocument document = XDocument.Parse(e.Result);
                var current = from query in document.Descendants("current_condition")
                                     select new WeatherModel
                                     {
                                         ObservationTime = DateTime.Parse((string)query.Element("localObsDateTime")).ToString("HH:mm tt"),
                                         Temperature = (string)query.Element("temp_C"),
                                         WeatherIconURL = (string)query.Element("weatherIconUrl"),
                                         Humidity = (string)query.Element("humidity"),
                                         WindSpeedKmph = (string)query.Element("windspeedKmph")
                                     };             

                this.Forecasts = (from query in document.Descendants("weather")
                                       select new WeatherModel
                                       {
                                           Date = DateTime.Parse((string)query.Element("date")).ToString("dddd"),
                                           TempMaxC = (string)query.Element("tempMaxC"),
                                           TempMinC = (string)query.Element("tempMinC"),
                                           WeatherIconURL = (string)query.Element("weatherIconUrl")
                                       }).ToList();
            }
        }
    }
}

WeatherView.xaml

<UserControl x:Class="JendelaBogor.Views.WeatherView"
    xmlns:vm="clr-namespace:JendelaBogor.ViewModels">

    <UserControl.DataContext>
         <vm:WeatherViewModel />
    </UserControl.DataContext>

    <Grid Margin="0,-10,0,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid x:Name="Current" Grid.Row="0" Height="150" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Image Grid.Column="0" delay:LowProfileImageLoader.UriSource="{Binding WeatherIconURL}" Width="120" Height="120" VerticalAlignment="Top"/>
            <StackPanel Grid.Column="1" Height="200" VerticalAlignment="Top">
                <TextBlock Text="{Binding Temperature}" FontSize="22"/>
                <TextBlock Text="{Binding ObservationTime}" FontSize="22"/>
                <TextBlock Text="{Binding Humidity}" FontSize="22"/>
                <TextBlock Text="{Binding Windspeed}" FontSize="22"/>
            </StackPanel>
        </Grid>

        <Grid Grid.Row="1" Height="300"  VerticalAlignment="Bottom" Margin="10,0,0,0">
            <StackPanel VerticalAlignment="Top">
                <StackPanel Height="40" Orientation="Horizontal" Margin="0,0,0,0">
                    <TextBlock Text="Date" FontSize="22" Width="170"/>
                    <TextBlock Text="FC" FontSize="22" Width="60"/>
                    <TextBlock Text="Max" TextAlignment="Right" FontSize="22" Width="90"/>
                    <TextBlock Text="Min" TextAlignment="Right" FontSize="22" Width="90"/>
                </StackPanel>

                <StackPanel Orientation="Horizontal">
                    <ListBox ItemsSource="{Binding Forecasts}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Height="40" Orientation="Horizontal" Margin="0,10,0,0">
                                    <TextBlock Text="{Binding Date}" FontSize="22" TextAlignment="Left" Width="170" />
                                    <Image delay:LowProfileImageLoader.UriSource="{Binding WeatherIconURL}" Width="40" Height="40" />
                                    <TextBlock Text="{Binding TempMaxC, StringFormat='\{0\} °C'}" TextAlignment="Right" FontSize="22" Width="90" />
                                    <TextBlock Text="{Binding TempMinC, StringFormat='\{0\} °C'}" TextAlignment="Right" FontSize="22" Width="90" />
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>
            </StackPanel>
        </Grid>
    </Grid>
</UserControl>

MainPage.xaml

<controls:PanoramaItem x:Name="Weather" Header="weather">
    <views:WeatherView />
</controls:PanoramaItem>
4

2 に答える 2

2

使用しているビューモデルをビューに通知する必要があります。追加することにより

<UserControl
    xmlns:vm="clr-namespace:JendelaBogor.ViewModels">

    <UserControl.DataContext>
       <vm:WeatherViewModel />
    </UserControl.DataContext>

</UserControl>

すべて{Binding}のはクラスにマップされWeatherViewModelます。リードが示唆するようにリストボックスのプロパティを使用することItemsSourceで、プロパティを介して公開するリストのすべてのアイテムをバインドできます。

アプリケーションの実行中にリストが変更された場合は、を使用してリストObservableCollectionをクリアし、新しいデータを受信したときにすべての新しいアイテムを追加することを検討してください。そうした場合、GUIはそれで更新されます。

于 2013-01-23T18:27:20.203 に答える
1

ViewModelはビューについて知りません。

ForecastsViewModelにプロパティを作成し、ViewからItemsSourceをプロパティにバインドする必要があります。ビューで、を次のように変更しますListBox

<!-- No need for a name - just add the binding -->
<ListBox ItemsSource="{Binding Forecasts}">

次に、ViewModelに次を追加します。

// Add a backing field
private IList<WeatherModel> forecasts;

// Add a property implementing INPC
public IList<WeatherModel> Forecasts 
{ 
    get { return forecasts; }
    private set
    {
        forecasts = value;
        this.RaisePropertyChanged("Forecasts");
    }
}

次に、これをメソッドで設定できます。

 this.Forecasts = (from query in document.Descendants("weather")
                             select new WeatherModel
                             {
                                 Date = DateTime.Parse((string)query.Element("date")).ToString("dddd"),
                                 TempMaxC = (string)query.Element("tempMaxC"),
                                 TempMinC = (string)query.Element("tempMinC"),
                                 WeatherIconURL = (string)query.Element("weatherIconUrl")
                             })
                 .ToList(); // Turn this into a List<T>
于 2013-01-23T17:19:32.883 に答える