首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >INotifyPropertyChanged/Binding?

INotifyPropertyChanged/Binding?
EN

Stack Overflow用户
提问于 2016-03-31 05:09:33
回答 2查看 393关注 0票数 1

我正在设法从另一个线程中更新我的主UI (例如textblock)。到目前为止,我能够做到这一点的唯一方法是使用able对象。我遇到了一种情况,我不能使用and对象,最近有人告诉我使用MVVM / binding方法。我看了一些视频,做了一些例子,但我似乎无法让它发挥作用。

代码语言:javascript
复制
<TextBlock Name="txtblock1" Text="{Binding count}"></TextBlock>

这是我的错误

异常引发:“System.Runtime.InteropServices.COMException”在System.Runtime.WindowsRuntime.dll异常中抛出:“System.Runtime.InteropServices.COMException”在mscorlib.ni.dll异常中抛出:“System.Runtime.InteropServices.COMException”在mscorlib.ni.dll中

视图(代码后面)

代码语言:javascript
复制
public sealed partial class MainPage : Page 
{
    public MainPage()
    {
        this.InitializeComponent();
        ViewModelexample obj = new ViewModelexample();
        txtblock1.DataContext = obj;
        obj.Methodasync();
    }
}

ViewModel

代码语言:javascript
复制
public class ViewModelexample : INotifyPropertyChanged
{
    public string count { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void onPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler !=null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }


    public async void Methodasync()
    {
        await Method();         
    }

    public Task Method()
    {
        return Task.Factory.StartNew(() =>
        {
            for (int i = 0; i < 100; i++)
            {
                Task.Delay(1000).Wait();
                Debug.WriteLine(i.ToString());
                count = i.ToString();
                onPropertyChanged(i.ToString());
            }
        });
    }
}

对我可能做错了什么有什么想法吗?

谢谢

EN

回答 2

Stack Overflow用户

发布于 2016-03-31 05:21:51

您的count属性需要能够通知它已经更改。

代码语言:javascript
复制
public class ViewModelexample : INotifyPropertyChanged
{    
    private string _count;
    public string count { 
        get { return _count; } 
        set {
            if(value != _count) {
                _count = value;
                OnPropertyChanged(nameof(count));
            }
        } 
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        // the new Null-conditional Operators are thread-safe:
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private int _testCount = 0;
    public void Method() {
        testCount++;
        Debug.WriteLine(testCount.ToString());
        count = testCount.ToString();
    }

}

上述操作之所以有效,是因为新的空条件运算符是螺纹安全

空条件成员访问的另一个用途是以线程安全的方式以更少的代码调用委托。..。这种新方法是线程安全的,因为编译器只生成一次计算PropertyChanged的代码,将结果保存在一个临时变量中。

要测试它,您可以编辑ViewModel方法,并让视图调用一个事件,比如加载页面或单击按钮。

代码语言:javascript
复制
public sealed partial class MainPage : Page 
{
    ViewModelexample obj = null;
    public MainPage()
    {
        this.InitializeComponent();
        obj = new ViewModelexample();
        this.DataContext = obj;        
    }

    public void OnSomeEventHandler() {
        obj.Method();
    }
}
票数 3
EN

Stack Overflow用户

发布于 2016-03-31 10:47:30

我的假设是绑定将处理交叉线程调用。

不,这只适用于一些MVVM框架(如WPF)。因此,我更愿意把我所有的ViewModels都看作是UI的一部分。

使用代码示例,您应该能够使用Progress<T>

代码语言:javascript
复制
public async void Methodasync()
{
  var progress = new Progress<int>(value =>
  {
    count = value;
    onPropertyChanged("count");
  });
  await Method(progress);
}

public Task Method(IProgress<int> progress)
{
  return Task.Run(() =>
  {
    for (int i = 0; i < 100; i++)
    {
      Task.Delay(1000).Wait();
      Debug.WriteLine(i.ToString());
      progress.Report(i);
    }
  });
}

还请注意,我从StartNew更改为Run。一般情况下,不要将StartNew用于我在博客上描述的原因

如果您“非常严肃”由于一些奇怪的原因不能使用Progress<T>,那么您可以直接使用反应性扩展或SynchronizationContext

使用SynchronizationContext的示例

代码语言:javascript
复制
public Task Method()
{
  var context = SynchronizationContext.Current;
  return Task.Run(() =>
  {
    for (int i = 0; i < 100; i++)
    {
      Task.Delay(1000).Wait();
      Debug.WriteLine(i.ToString());
      var localI = i;
      context.Post(() =>
      {
        count = localI;
        onPropertyChanged("count");
      });
    }
  });
}

localI是给避免关闭循环变量的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36324612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档