Windows Phone数据绑定:跨线程
本文关键字:线程 数据绑定 Phone Windows | 更新日期: 2023-09-27 18:16:09
我们在Windows phone(使用xaml)上有一个数据绑定问题。我创建了一个简单的示例,它应该允许再现这个问题。这是我们的模型类:
public class Data : INotifyPropertyChanged
{
private int value = 0;
public int Value
{
get
{
return value;
}
set
{
this.value = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Value"));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public Data()
{
var t = new Thread(new ThreadStart(() =>
{
while (true)
{
Thread.Sleep(2000);
Value += 1;
}
}));
t.IsBackground = true;
t.Start();
}
}
使用一个线程来更新value-property并触发PropertyChanged-event。
现在我想把这个值属性绑定到一个gui控件:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock Text="{Binding Path=Value}" />
</Grid>
public MainPage()
{
InitializeComponent();
DataContext = new Data();
}
当值第一次更改时(并且触发PropertyChanged-event),数据绑定系统尝试复制data的值。值为TextBlock。文本,这会导致无效的跨线程异常,因为此事件没有在ui线程上触发。
我的问题:.NET数据绑定框架不应该认识到我绑定到一个ui控件并执行线程切换本身?我知道我可以简单地使用调度程序在主线程上触发PropertyChanged-event,但我想让我的模型类与gui组件分开。这个问题有更好的解决办法吗?我无法使用DependencyObject方法,因为我们的核心项目(包含模型类)应该在Windows Phone和Android上运行,而Android不支持System.Windows-namespace。
解决这个问题的一种方法是在视图模型上存储对调度程序的引用,并且仅在它不为空时使用它来执行属性更改事件。然后你可以在VM的构造函数中设置dispatcher属性。
我这样做:
public event PropertyChangedEventHandler PropertyChanged;
private void PropertyEventChanged(string propertyName)
{
if (PropertyChanged == null) return;
if (Application.OpenForms.Count > 0 && Application.OpenForms[0].InvokeRequired)
Application.OpenForms[0].Invoke(new MethodInvoker(() => PropertyChanged(this, new PropertyChangedEventArgs(propertyName))));
else
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}