通过转换器更新绑定到DataRow的DataGridColumn的目标

时间:2017-03-11 00:06:08

标签: c# wpf mvvm datagrid strongly-typed-dataset

此问题与https://stackoverflow.com/questions/42611351/cannot-bind-to-additional-properties-on-typed-datarow

有关

我现在所做的是使用转换器使用我从类型化数据行中的其他字段计算的值填充数据网格列。初始更新时工作正常。当我更改计算值所依赖的行值之一时,问题就出现了。我无法弄清楚如何更新计算目标。

这是XAML ......

<Window.Resources>
    <local:FullNameConverter x:Key="FullNameConverter"/>
</Window.Resources>
<Grid>
    <DataGrid ItemsSource="{Binding TableA}" AutoGenerateColumns="False" >
            <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Name}"  Width="30*" Header="Name" SortDirection="Ascending" />
            <DataGridTextColumn Header="Value" Width="30*" Binding="{Binding Value}"/>
            <DataGridTextColumn Header="Full Name" Width="30*" 
                                Binding="{Binding Converter={StaticResource FullNameConverter}}" IsReadOnly="True"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

这是背后的代码......

public partial class BindingBench : Window
{
    SimplyDataSet _dataSet = new SimplyDataSet();
    public BindingBench()
    {
        InitializeComponent();
        _dataSet.TableA.Columns.Add(new DataColumn("FullName",typeof(string)));
        SimplyDataSet.TableARow arow = _dataSet.TableA.AddTableARow("Z", 0.0);
        arow = _dataSet.TableA.AddTableARow("X", 1.0);
        arow = _dataSet.TableA.AddTableARow("Y", 2.0);
        DataContext = this;
    }
    public DataTable TableA
    {
        get { return _dataSet.TableA; }
    }
}

这是转换器...

public class FullNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        DataRowView rv = value as DataRowView;
        if(rv != null)
        {
            SimplyDataSet.TableARow row = rv.Row as SimplyDataSet.TableARow;
            if (row != null)
            {
                return row.Name + "=" + row.Value;
            }
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

最后这里是输入的数据集......

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="SimplyDataSet"  targetNamespace="http://tempuri.org/SimplyDataSet.xsd" xmlns:mstns="http://tempuri.org/SimplyDataSet.xsd" xmlns="http://tempuri.org/SimplyDataSet.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:annotation>
<xs:appinfo source="urn:schemas-microsoft-com:xml-msdatasource">
  <DataSource DefaultConnectionIndex="0" FunctionsComponentName="QueriesTableAdapter" Modifier="AutoLayout, AnsiClass, Class, Public" SchemaSerializationMode="IncludeSchema" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
    <Connections />
    <Tables />
    <Sources />
  </DataSource>
</xs:appinfo>
</xs:annotation>
<xs:element name="SimplyDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msprop:EnableTableAdapterManager="true" msprop:Generator_DataSetName="SimplyDataSet" msprop:Generator_UserDSName="SimplyDataSet">
<xs:complexType>
  <xs:choice minOccurs="0" maxOccurs="unbounded">
    <xs:element name="TableA" msprop:Generator_TableClassName="TableADataTable" msprop:Generator_TableVarName="tableTableA" msprop:Generator_TablePropName="TableA" msprop:Generator_RowDeletingName="TableARowDeleting" msprop:Generator_RowChangingName="TableARowChanging" msprop:Generator_RowEvHandlerName="TableARowChangeEventHandler" msprop:Generator_RowDeletedName="TableARowDeleted" msprop:Generator_UserTableName="TableA" msprop:Generator_RowChangedName="TableARowChanged" msprop:Generator_RowEvArgName="TableARowChangeEvent" msprop:Generator_RowClassName="TableARow">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="Name" msprop:Generator_ColumnVarNameInTable="columnName" msprop:Generator_ColumnPropNameInRow="Name" msprop:Generator_ColumnPropNameInTable="NameColumn" msprop:Generator_UserColumnName="Name" type="xs:string" minOccurs="0" />
          <xs:element name="Value" msprop:Generator_ColumnVarNameInTable="columnValue" msprop:Generator_ColumnPropNameInRow="Value" msprop:Generator_ColumnPropNameInTable="ValueColumn" msprop:Generator_UserColumnName="Value" type="xs:double" minOccurs="0" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xs:choice>
</xs:complexType>
  </xs:element>
</xs:schema>

注意:

  1. 这是一套完整的代码。您没有看到TableA或AddTableARow的实现的原因是有一个工具(XSD)生成实现数据集的代码。我也可以添加这个生成的代码,但即使对于像这样的小数据集也是如此,否则它不是很有帮助。
  2. 在我看来,我遇到的这两个相关问题的基本问题是DataGridColumn通过DataRowView绑定到DataRow。我正在向基础DataRow添加内容而无法修改DataRowView的行为。因此,在我看来,DataSet与MVVM根本不兼容。但是,我似乎无法找到任何意见,应该避免使用DataSet以支持其他内容。
  3. 我已经尝试了多种方法来更新计算单元格,包括DataRowView.BeginEdit()/ EndEdit(),在DataRow上实现INotifyPropertyChanged等。
  4. 我可以通过刷新数据源来获取要更新的计算列。这不是解决方案!我可以继续更新单行中的所有单元格,但不会更新每个单元格。
  5. 欢迎任何想法或建议。

1 个答案:

答案 0 :(得分:0)

我不熟悉您的SimplyDataSet课程,但我建议绑定到CollectionViewSource并将您的数据集分配给CollectionViewSource.Source CollectionViewSource代理,它实现INotifyPropertyChanged以正确更新您的UI,并维护与底层数据源的连接。

public partial class BindingBench : Window
{
    CollectionViewSource dbViewsource = new CollectionViewSource();
    SimplyDataSet _dataSet = new SimplyDataSet();
    public BindingBench()
    {
        InitializeComponent();
        _dataSet.TableA.Columns.Add(new DataColumn("FullName", typeof(string)));
        SimplyDataSet.TableARow arow = _dataSet.TableA.AddTableARow("Z", 0.0);
        arow = _dataSet.TableA.AddTableARow("X", 1.0);
        arow = _dataSet.TableA.AddTableARow("Y", 2.0);
        dbViewsource.Source = _dataSet  //This could possibly be _dataSet.GetDefaultView()
        DataContext = dbViewSource.View;
    }
    public DataTable TableA
    {
        get { return _dataSet.TableA; }
    }
}

可以在此处找到更深入的示例: https://msdn.microsoft.com/en-us/library/dd547149.aspx