0

我正在尝试创建一个从网站获取数据并显示它们的 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;
    }
}
[...]
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 知道了这个 App。只需使用:

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