C#数据绑定类变量

时间:2010-07-01 16:53:09

标签: c# .net data-binding event-handling

我真的爱上了整个.Net数据绑定方案......但显然还有一些问题。假设我的类有一个名为Susan的double类型的成员变量。那么似乎没有立即将Susan绑定到文本框SusanText的方法,因为绑定看起来像这样

SusanText.DataBindings.Add("Text",datasource,"Property")

并且Susan不是属性。所以我可以让Susan成为一个公共财产,但那有点臭...如果我想隐藏Susan怎么办? (我想我可以使Susan成为某个内部类的私有实例的公共属性......但这需要很多工作才能实现一点点。)但是,我遇到了更大的问题,所以对于争论的缘故让我们继续这样做:

private double Susan_;
public double Susan{ get; set;}
...
SusanText.DataBindings.Add("Text",this,"Susan")

然后一切似乎都按预期工作。如果我改变SusanTextSusan会相应改变。但是,当我直接改变Susan时,问题就出现了。我希望SusanText能够自动更新。所以我怀疑我需要使Susan成为实现某种IBindable接口的double的子类,这样如果Susan被数据绑定到SusanText,则会注册相应的事件并Susan如果她被修改,将通知其他人。

Susan做我想让她做的最简单的方法是什么?

谢谢!

2 个答案:

答案 0 :(得分:3)

DataBinding期望它所绑定的类引发INotifyPropertyChanged以指示某个值已被更改并需要重新读取;不幸的是,实现这一点仍然需要一些手动编码(或类似PostSharp到IL编织必要的代码)。

因此,为了支持数据绑定,您不能使用自动实现的属性,也不能直接绑定到字段 - 也不会让您有机会提出必要的事件(绑定将起作用,但值不会更新)什么时候改变了。)

DataBinding的另一个缺点是它不考虑线程。如果后台线程修改了数据绑定值,那么数据绑定将尝试进行跨线程调用以更新UI - 这很糟糕。我发现最好的解决方法是让可绑定类包含其UI Synchronization Context的实例,这样可以确保在UI线程上调用UI的更新。

using System.ComponentModel;

namespace MyWebGrocer.Uma.UI
{
  public class BoundClass : INotifyPropertyChanged
  {
    private string _Name;

    private int _Age;

    public event PropertyChangedEventHandler PropertyChanged;

    public string Name
    {
      get
      {
        return _Name;
      }
      set
      {
        _Name = value;
        OnPropertyChanged("Name");
      }
    }

    public int Age
    {
      get
      {
        return _Age;
      }
      set
      {
        _Age = value;
        OnPropertyChanged("Age");
      }
    }

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

我知道这一切听起来令人沮丧 - 数据绑定的这些缺点是通过艰难的方式学到的。然而,在它们表现为更大的问题之前,最好早点意识到并补偿这些问题。

答案 1 :(得分:0)

很难在不知道代码如何组合的情况下告诉您最简单的方法。如果你在代码中设置绑定,看起来你仍然在努力工作。

这是最简单的方法:

namespace MyProject
{
    public sealed class ViewModel : DependencyObject //handles all databinding voodoo
    {
        public string Susan
        {
            get { return (string)GetValue(SusanProperty); }
            set { SetValue(SusanProperty, value); }
        }

        public static readonly DependencyProperty 
            SusanProperty = DependencyProperty.Register
                ("Susan", typeof(string), 
                typeof(ViewModel));
    }
}

并在xaml中:

<Window.DataContext>
  <ViewModel xmlns="clr-namespace:MyProject" />
</Window.DataContext>
<Grid>
  <TextBox Text="{Binding Susan}" />
</Grid>