2012-12-29 127 views
0

我試圖創建一個WP8應用程序,它從網站獲取數據並顯示它們。 我選擇了全景模板,Visual Studio創建了一些默認代碼。WP8綁定不更新

我想要做的是,如果我更改文本綁定到的變量文本塊會自動更新。但調用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)); 
     } 
    } 
} 

UPDATE 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; 
    } 
} 
[...] 

回答

0
<TextBlock.DataContext> 
    <ViewModels:MainViewModel/> 
</TextBlock.DataContext> 

這將創建一個新的MainViewModel對象,你沒有更新此對象,但您存儲在應用程序對象中的一個。

爲了解決這個問題:設置查看到App.ViewModel對象(無需設置TextBlock的數據上下文)

的數據上下文外:請不要使用此代碼:

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

現在你的ViewModel知道應用程序。只需使用:

public void changeDate() 
{ 
    Date = "fu"; 
} 
+0

如果刪除了正文塊的數據上下文,並設置「的DataContext = App.ViewModel;」在MainPage構造函數中,文本塊是空的 – user1796724

+0

您在哪裏初始化App.ViewModel?你可以發佈該代碼嗎? –

+0

我又添加了兩個片段 – user1796724

1

我認爲正在發生的事情是,你NotifyPropertyChanged從一些輔助線程這可能導致來自同一個工作線程調用日期吸氣調用。如果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)); 
     }); 
    } 
} 

希望它能幫助