none
数据绑定的问题 RRS feed

  • 问题

  • 我刚学WPF,刚了解了数据绑定,现在想实现一些比较复杂的功能,示例在下面:

    '--------------------源对象
    Public bigobj As New Big
    '--------------------数据
    Public Class Big
        Private _d1 As Little1
        Private _d2 As Little2
        Public Property D1() As Little1
            Get
                Return _d1
            End Get
            Set(ByVal value As Little1)
                _d1 = value
            End Set
        End Property
        Public Property D2() As Little2
            Get
                Return _d2
            End Get
            Set(ByVal value As Little2)
                _d2 = value
            End Set
        End Property
    End Class
    
    Public Class Little1
        Private _x(5) As Integer
        Public Property X(ByVal i As Integer) As Integer
            Get
                Return _x(i)
            End Get
            Set(ByVal value As Integer)
                _x(i) = value
                '????
            End Set
        End Property
    End Class
    
    Public Class Little2
        Private _y As Integer
        Public Property Y() As Integer
            Get
                Return _y
            End Get
            Set(ByVal value As Integer)
                _y = value
                '????
            End Set
        End Property
    End Class
    '--------------------控件
    Public Class MyCanvas
        Inherits Canvas
        Private Tx(5), Ty As TextBox
        Public Sub New()
            CreateBinding()
        End Sub
        Public Sub CreateBinding()
            Dim bind As New Binding()
            '????
        End Sub
    End Class
    我想在加载 MyCanvas 实例的时候创建绑定,将 Tx(0-5) 绑定到 bigobj.D1.X(0-5),Ty 绑定到 bigobj.D2.Y,只用那一个 bind 对象来完成,三个问号处代码怎么写呢?谢谢了(MSDN 上面的数据绑定示例是绑定元数据,我照着写无法实现绑定对象成员当中的数据成员,因此请帮我完成那三处代码)
    2009年11月4日 3:59

答案

  • 楼主你好,
    -->只用那一个 bind 对象来完成,三个问号处代码怎么写呢?谢谢了(MSDN 上面的数据绑定示例是绑定元数据,我照着写无法实现绑定对象成员当中的数据成员,因此请帮我完成那三处代码.

    我想你要实现的binding功能并不是在三个问号中实现的,而是在CreateBinding方法中实现的,那三个属情访问器(Set)中你只要像一般的设置值就可以了。并且我想你这里要实现的是多个binding,一个binding实例并不可行,你可以试一下我下面提供的代码段:

    public
    void CreateBinding()

            {

                for (int i = 0; i <Tx.Length; i++)

               {

                   Binding bind = new Binding();

                    bind.Path = new PropertyPath(".");

                    //make the X property return _x, not _x[i];

                    bind.Source = new List<int> { new Big().D1.X[i] };

                    Tx[i].SetBinding(TextBox.TextProperty, bind);

               }

            }

    如有疑问,请继续回复.
    谢谢.


    Jim Zhou -MSFT
    2009年11月5日 6:55
    版主

全部回复

  • 楼主你好,
    -->只用那一个 bind 对象来完成,三个问号处代码怎么写呢?谢谢了(MSDN 上面的数据绑定示例是绑定元数据,我照着写无法实现绑定对象成员当中的数据成员,因此请帮我完成那三处代码.

    我想你要实现的binding功能并不是在三个问号中实现的,而是在CreateBinding方法中实现的,那三个属情访问器(Set)中你只要像一般的设置值就可以了。并且我想你这里要实现的是多个binding,一个binding实例并不可行,你可以试一下我下面提供的代码段:

    public
    void CreateBinding()

            {

                for (int i = 0; i <Tx.Length; i++)

               {

                   Binding bind = new Binding();

                    bind.Path = new PropertyPath(".");

                    //make the X property return _x, not _x[i];

                    bind.Source = new List<int> { new Big().D1.X[i] };

                    Tx[i].SetBinding(TextBox.TextProperty, bind);

               }

            }

    如有疑问,请继续回复.
    谢谢.


    Jim Zhou -MSFT
    2009年11月5日 6:55
    版主
  • 调试了一下午,晚上才发现原来 Friend 属性是不能参与绑定的…………
    bind.Source = new List { new Big().D1.X[i] };
    一句我在 VB.NET 里面写成
    bind.Source = New List(Of Int32) {New Big.D1.X(i)}
    语法是错的,请教一下应该怎么写……如果我直接把它写成
    bind.Source = Big.D1.X(i) 结果效果就会变成 OneTime 绑定,该怎么做呢?谢谢答疑

    另外就是个不成问题的小问题,采用这种方法需要设置数组属性 Property X As Int32(),而这样设置会引起警告错CA1819“属性不应返回数组”。虽然不影响运行,毕竟感觉破坏了代码的规范性,在解决上述问题的基本前提下有没有方法解决这个小问题呢(就是让这个警告错消失的同时又不引发新的警告错)?
    • 已编辑 Clannad 2009年11月5日 14:12 为什么不能换行呢?
    2009年11月5日 14:11
  • Hi,
    -->bind.Source = Big.D1.X(i) 结果效果就会变成 OneTime 绑定,该怎么做呢?谢谢答疑
    你可以自己手动设置binding的mode,像下面这样,
    bind.Mode = BindingMode.TwoWay;
    -->另外就是个不成问题的小问题,采用这种方法需要设置数组属性 Property X As Int32(),而这样设置会引起警告错CA1819“属性不应返回数组”。

    不好意思,因为我习惯用的是C#,我把上面你的类转成C#, 并把那个属性X返回一个int[],不会出现警告错误,我想VB中属性也是可以包括数组类型的,你可以再确认一下.

    -->为什么不能换行呢?
    楼主你是说哪里不能换行呢?


    谢谢.

    Jim Zhou -MSFT
    2009年11月6日 8:05
    版主
  • 您好:

    按我上面的写法,我就是显式设置了 Mode = BindMode.TwoWay 以后,它达到的效果仍然是 OneTime 绑定,所以我才很疑惑(Tx(i) 显示的确实是创建绑定时的 X(i) 值,说明绑定成功了,然而修改 Tx(i) 不影响 X(i),修改 X(i) 也不影响 Tx(i))。这可能是什么问题呢?

    您给出的 bind.Source = new List { new Big().D1.X[i] };这句代码是否表示下面的内容,是一句采用了集合初始化器的语句?
    List l = new List();
    l.Add(Big.D1.X[i]);
    如果是这个意思,不知道 VB.NET 中有没有相应的一行代码完成创建集合和添加元素的功能,没有的话我只好老老实实写成两句了

    CA1819警告错(属性不应返回数组)不是直接显示的,是“运行代码分析”后才会显示的,所以我说是个不成问题的小问题~

    谢谢答疑!

    我说的不能换行,是指上次回帖后,我本来换好行的内容全部被连成一行了,编辑后才正常
    • 已编辑 Clannad 2009年11月6日 9:24 还是那个问题
    2009年11月6日 9:14
  • 您好:

    我终于理解了 bind.Source = new List { new Big().D1.X[i] };的含义。但由此我推测这一句是创建了新的 Big 对象,因此并不能与 bigobj 的内容进行绑定;即使改成 bind.Source = new List { bigobj.D1.X[i] };也是绑定到 X[i] 的副本,而并没有绑定到 X[i] 本身,不知道我的推测对吗?

    经过测试您给的第一种方法:

    bind.Source = bigobj.D1.X[i];
    bind.Path = ".";
    //此种情况下下面的绑定模式设置无效,得到的是 OneTime 绑定
    bind.Mode = BindingMode.TwoWay;
    Tx[i].SetBinding....

    后来又发现了第二种方法:

    bind.Source = bigobj.D1
    bind.Path = "X[" & i.ToString & "]";
    //此种情况下绑定模式有效
    bind.Mode = BindingMode.TwoWay;
    Tx[i].SetBinding....

    虽然绑定成功了,但又发现新的问题:
    在代码中对 X[i] 的修改并不会引发 public int[] X 的 set 过程,从而 OnPropertyChanged("X");无法被触发,只能手动引发,明显破坏了UI与数据的解耦;
    在实际应用中我的应用必须在 X 的元素 X[i] 改变时添加与 i 有关的处理代码,所以必须应用 public int X(int i) 而不是 public int[] X,而这第二种方法仍然不能应用于 public int X(int i) 的情况。

    期望我的新问题能得到您的关注,谢谢!
    • 已编辑 Clannad 2009年11月9日 8:28 换行的问题
    2009年11月9日 8:26
  • 楼主你好,
    -->在代码中对 X[i] 的修改并不会引发 public int[] X 的 set 过程,从而 OnPropertyChanged("X");无法被触发,只能手动引发,明显破坏了UI与数据的解耦;

    你对x[i]数组的改改变没有引发set方法体的代码执行,是因为Arrary没有执行INotifyCollectionChanged和INotifyPropertyChanged,这种情况下,我建议你用一个ObservableCollection<T>来做.

    谢谢。
    Jim Zhou -MSFT
    2009年11月10日 8:32
    版主