繁体   English   中英

WPF。 为 DataContext 属性赋值不会改变绑定属性的值

[英]WPF. Assigning a value to the DataContext property doesn't change the value of the bound property

为 DataContext 属性分配值不会更改绑定属性的值。

我需要为表中的每条记录多次获取绑定属性的值,以计算 DataGrid 中列的总和值。

为此,我使用了一个特殊的虚拟 FrameworkElement object。

object 代码如下所示:

  public class BindValueReader : FrameworkElement
  {
    public static readonly DependencyProperty ValueProperty =
      DependencyProperty.Register("Value",
                                  typeof(object),
                                  typeof(BindValueReader),
                                  new PropertyMetadata(null));

    public object Value
    {
      get { return GetValue(ValueProperty); }
      set { SetValue(ValueProperty, value); }
    }
  }

它仅用于从绑定中获取值。

我使用以下代码来获取每条记录的绑定属性的值。

  Decimal sumVal = 0;
  foreach (DataRowView rowView in view)
  {
    BindValueReader valueReader = new BindValueReader();
    valueReader.DataContext = rowView;
    valueReader.SetBinding(BindValueReader.ValueProperty, bdn);
    if (valueReader.Value != null)
      sumVal += (Decimal)valueReader.Value;
  }

它工作正常,但速度相当慢。

当我尝试像这样优化代码时

  Binding bdn = new Binding("Income");

  BindValueReader valueReader = new BindValueReader();
  valueReader.SetBinding(BindValueReader.ValueProperty, bdn);

  DataView view = dataTable.DefaultView;
  Decimal sumVal = 0;

  foreach (DataRowView rowView in view)
  {
    valueReader.DataContext = rowView;
    if (valueReader.Value != null)
      sumVal += (Decimal)valueReader.Value;
  }

它停止工作。

我不知道为什么。

这是完整的程序代码:

XAML:

<Window x:Class="EhLibTestApp.TestWindow1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:EhLibTestApp"
        mc:Ignorable="d"
        Title="TestWindow1" Height="450" Width="800">
    <Grid>
    <StackPanel HorizontalAlignment="Stretch" Height="63" VerticalAlignment="Top" Orientation="Horizontal" >
      <Button Content="Button" Width="87" Margin="10" Click="Button_Click"/>
    </StackPanel>

  </Grid>
</Window>

CS:

using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Data;
using System.Diagnostics;

namespace EhLibTestApp
{
  /// <summary>
  /// Interaction logic for TestWindow1.xaml
  /// </summary>
  public partial class TestWindow1 : Window
  {
    public TestWindow1()
    {
      InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
      DataTable dataTable = new DataTable();
      dataTable.Columns.Add("EmployeeID", typeof(Int32));
      dataTable.Columns.Add("LastName", typeof(String));
      dataTable.Columns.Add("Income", typeof(System.Decimal));

      dataTable.Rows.Add(1, "Davolio", 100);
      dataTable.Rows.Add(2, "Fuller", 100);
      dataTable.Rows.Add(3, "Leverling", 100);
      dataTable.Rows.Add(4, "Peacock", DBNull.Value);

      Debug.WriteLine("");
      Debug.WriteLine("Test1");
      Test1(dataTable);

      Debug.WriteLine("");
      Debug.WriteLine("Test2");
      Test2(dataTable);
    }

    private void Test1(DataTable dataTable)
    {
      Binding bdn = new Binding("Income");
      DataView view = dataTable.DefaultView;

      int ticks = Environment.TickCount;
      Decimal sumVal = 0;
      foreach (DataRowView rowView in view)
      {
        BindValueReader valueReader = new BindValueReader();
        valueReader.DataContext = rowView;
        valueReader.SetBinding(BindValueReader.ValueProperty, bdn);
        if (valueReader.Value != null)
          sumVal += (Decimal)valueReader.Value;
      }

      Debug.WriteLine("Sum of Income = " + sumVal.ToString());
      Debug.WriteLine("Ticks = " + (Environment.TickCount - ticks).ToString());
    }

    private void Test2(DataTable dataTable)
    {
      Binding bdn = new Binding("Income");

      BindValueReader valueReader = new BindValueReader();
      valueReader.SetBinding(BindValueReader.ValueProperty, bdn);

      DataView view = dataTable.DefaultView;
      Decimal sumVal = 0;
      int ticks = Environment.TickCount;

      foreach (DataRowView rowView in view)
      {
        valueReader.DataContext = rowView;
        if (valueReader.Value != null)
          sumVal += (Decimal)valueReader.Value;
      }

      Debug.WriteLine("Sum of Income = " + sumVal.ToString());
      Debug.WriteLine("Ticks = " + (Environment.TickCount - ticks).ToString());
    }
  }

  public class BindValueReader : FrameworkElement
  {
    public static readonly DependencyProperty ValueProperty =
      DependencyProperty.Register("Value",
                                  typeof(object),
                                  typeof(BindValueReader),
                                  new PropertyMetadata(null));

    public object Value
    {
      get { return GetValue(ValueProperty); }
      set { SetValue(ValueProperty, value); }
    }
  }

}

调试 Output:

Test1
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Income; DataItem='DataRowView' (HashCode=22689808); target element is 'BindValueReader' (Name=''); target property is 'Value' (type 'Object')
Sum of Income = 300
Ticks = 16

Test2
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Income; DataItem=null; target element is 'BindValueReader' (Name=''); target property is 'Value' (type 'Object')
Sum of Income = 0
Ticks = 0
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Income; DataItem='DataRowView' (HashCode=22689808); target element is 'BindValueReader' (Name=''); target property is 'Value' (type 'Object')

您正在尝试对收入属性求和。

您可以通过使用您获得的数据行视图中的列而不是使用绑定来做到这一点。

foreach (DataRowView rowView in view)
{
   var val = rowView["Income"];
   if (val != null)
   {
      sumVal += (Decimal)val;
   }
}

不过,这不是使用 WPF 的好方法,您应该查看 MVVM,定义一个 class 实现 inotifypropertychanged 作为行视图模型。 将 itemssource 绑定到 this 的 observablecollection。 然后使用绑定集合和命名属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM