我正在尝试创建一个WP8应用程序,它从网站获取数据并显示它们。 我选择了全景模板,Visual Studio创建了一些默认代码。
我想要做的是,如果我更改文本绑定的变量,文本块会自动更新。但是调用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;
}
}
[...]
答案 0 :(得分: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));
});
}
}
希望有所帮助
答案 1 :(得分: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";
}