0

ウェブサイトからデータを取得して表示するWP8アプリを作成しようとしています。パノラマテンプレートを選択すると、VisualStudioによってデフォルトのコードが作成されました。

私がやろうとしているのは、テキストがバインドされている変数を変更すると、テキストブロックが自動的に更新されることです。ただし、changeDate()を呼び出してもUIは変更されません。テキストボックスにはまだ「dd.mm.yyyy」と表示されます。

MainPage.xaml:
<phone:LongListSelector.ListHeaderTemplate>
  <DataTemplate>
    <Grid Margin="12,0,0,38">
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
      </Grid.RowDefinitions>
      <TextBlock
          Text="{Binding Date}"
          Style="{StaticResource PanoramaItemHeaderTextStyle}"
          Grid.Row="0">
        <TextBlock.DataContext>
          <ViewModels:MainViewModel/>
        </TextBlock.DataContext>
      </TextBlock>
    </Grid>
  </DataTemplate>
</phone:LongListSelector.ListHeaderTemplate>

MainViewModel.cs:
public class MainViewModel : INotifyPropertyChanged
{
    [...]

    private string _date = "dd.mm.yyyy";
    public string Date
    {
        get
        {
            return _date;
        }
        set
        {
            if (value != _date)
            {
                _date = value;
                NotifyPropertyChanged("Date");
            }
        }
    }

    //public void changeDate()
    //{
    //    Date = "fu";
    //    App.ViewModel.Date = "bar";
    //}

**UPDATE 2**
    public bool IsDataLoaded
    {
        get;
        private set;
    }

    public void LoadData()
    {
        System.Net.WebClient wc = new System.Net.WebClient();
        wc.DownloadStringCompleted += wc_DownloadStringCompleted;
        wc.DownloadStringAsync(new Uri("somelink"));
    }

    private void wc_DownloadStringCompleted(object sender, System.Net.DownloadStringCompletedEventArgs e)
    {
        string s = FilterData(e.Result);
    }

    private string FilterData(string s)
    {
        string[] split = System.Text.RegularExpressions.Regex.Split(s, "<tbody>");
        s = split[1];
        split = System.Text.RegularExpressions.Regex.Split(s, "</tbody>");
        s = split[0];
        split = System.Text.RegularExpressions.Regex.Split(s, "\r\n");

        foreach(string str in split)
        {

            if (str.Contains("class=\"xl24\""))
            {
                App.ViewModel.Date = "somedate";
            }
        }

        return s;
    }
**END UPDATE 2**

[...]

    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

更新1

MainPage.xaml.cs:
public MainPage()
{
    InitializeComponent();

    DataContext = App.ViewModel;
}

**UPDATE 2**
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (!App.ViewModel.IsDataLoaded)
    {
        App.ViewModel.LoadData();
    }
}
**END UPDATE 2**

[...]

App.xaml.cs:
private static MainViewModel viewModel = null;

public static MainViewModel ViewModel
{
    get
    {
        if (viewModel == null)
            viewModel = new MainViewModel();

        return viewModel;
    }
}
[...]
4

2 に答える 2

1

私が考えているのは、NotifyPropertyChangedがワーカースレッドから呼び出され、同じワーカースレッドからDate getterが呼び出される可能性があることです。UI 要素が (メイン UI スレッドではなく) ワーカー スレッドからデータ ゲッターを呼び出す場合、操作は「無効なクロススレッド アクセス」で終了します。その場合は、メイン スレッドからハンドラを呼び出す必要があります。例えば:

private void NotifyPropertyChanged(String propertyName)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (null != handler)
    {
        Dispatcher dsp = Deployment.Current.Dispatcher;
        dsp.BeginInvoke(() => { 
            handler(this, new PropertyChangedEventArgs(propertyName));
        });
    }
}

それが役に立てば幸い

于 2013-12-24T14:41:40.907 に答える
0
<TextBlock.DataContext>
    <ViewModels:MainViewModel/>
</TextBlock.DataContext>

これにより、新しい MainViewModel オブジェクトが作成されます。このオブジェクトを更新するのではなく、App オブジェクトに保存したオブジェクトを更新します。

これを解決するには、View のデータ コンテキストを App.ViewModel オブジェクトに設定します (TextBlock のデータ コンテキストを設定する必要はありません)。

補足: このコードは使用しないでください:

public void changeDate()
{
    Date = "fu";
    App.ViewModel.Date = "bar";
}

これで、ViewModel はアプリについて認識しました。使用するだけです:

public void changeDate()
{
    Date = "fu";
}
于 2012-12-29T16:22:08.720 に答える