WPF将数据表行列绑定到文本框

WPF将数据表行列绑定到文本框,wpf,binding,datatable,viewmodel,Wpf,Binding,Datatable,Viewmodel,缩小的解决方案 我更接近,但不知道如何应用XAML来更改datacontext值。请根据需要查看以下原始问题的上下文 我的问题是我有一个ViewModel类作为窗口的datacontext。在这个视图模型上,我有一个“DataTable”对象(有列,只有一行用于测试)。当我尝试将文本框“TEXT”绑定设置到datatable的列时,它不起作用。我最终发现,无论我给它什么“来源”或“路径”,它都不会合作。然而,仅仅是通过玩弄各种场景,我就说了一通。让我们看看。Textbox控件有自己的“DataC

缩小的解决方案
我更接近,但不知道如何应用XAML来更改datacontext值。请根据需要查看以下原始问题的上下文

我的问题是我有一个ViewModel类作为窗口的datacontext。在这个视图模型上,我有一个“DataTable”对象(有列,只有一行用于测试)。当我尝试将文本框“TEXT”绑定设置到datatable的列时,它不起作用。我最终发现,无论我给它什么“来源”或“路径”,它都不会合作。然而,仅仅是通过玩弄各种场景,我就说了一通。让我们看看。Textbox控件有自己的“DataContext”属性。因此,在代码中,我只是强制使用textbox.DataContext=“MyViewModel.MyDataTableObject”并将路径留给它应该表示“MyDataColumn”的列,结果成功了

也就是说,如何为textbox控件编写XAML,使其“DataContext”属性设置为视图模型窗口的datatable对象的属性,但无法获得正确的属性。例:

<TextBox Name="myTextBox" 
    Width="120"
    DataContext="THIS IS WHAT I NEED" --- to represent
    Text="{Binding Path=DataName, 
                    ValidatesOnDataErrors=True,
                    UpdateSourceTrigger=PropertyChanged }" />
它确实起作用(当datatable在窗口(或视图模型)中作为公共可用时)

否则我会错过什么呢

更新:这是我在这里申请的示例代码的完整帖子。

使用System.ComponentModel;
使用系统数据;
命名空间WPFSample1
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共数据表滴滴涕;
公共主窗口()
{
初始化组件();
//连接到数据表
DDT=新的DerivedDataTable();
DataContext=this;
//启用此部件后,绑定工作正常。
//如果测试和绑定不起作用,则禁用此选项。
//但也要注意,我通过XAML手动尝试了这些设置。
object txt=FindName(“myTextBox”);
如果(txt是文本框)
{
Binding oBind=新绑定(“DataName”);
oBind.来源=滴滴涕;
oBind.Mode=BindingMode.TwoWay;
oBind.validateSondaerRors=true;
oBind.UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged;
((TextBox)txt).SetBinding(TextBox.TextProperty,oBind);
}
}
}
//带有钩子的泛型类,用于在数据表中启用错误捕获
//通过ColumnChanged事件与单个属性的IDataErrorInfo进行级别设置
公共类MyDataTable:DataTable
{
公共MyDataTable()
{
//钩柱转换
ColumnChanged+=MyDataColumnChanged;
}
受保护的无效MyDataColumnChanged(对象发送方,DataColumnChangeEventArgs e)
{ValidationTest(e.Row,e.Column.ColumnName);}
//对于任何派生数据表,只需定义验证方法
受保护的虚拟字符串验证测试(DataRow oDR,字符串ColumnName)
{返回“”;}
}
公共类DerivedDataTable:MyDataTable
{
公共派生数据表()
{
//简单数据表,一列一行,默认值为“X”
//因此,当窗口启动时,我知道窗体显示时它已正确绑定
//表单开始时的“X”初始值
添加(新的DataColumn(“DataName”,typeof(System.String));
列[“DataName”]。DefaultValue=“X”;
//向表中添加新行
添加(NewRow());
}
受保护的重写字符串验证测试(DataRow oDR,字符串ColumnName)
{
字符串错误=”;
开关(ColumnName.ToLower())
{
案例“dataname”:
if(string.IsNullOrEmpty(oDR[ColumnName].ToString())
||oDR[ColumnName].ToString().Length<4)
error=“Name至少4个字符”;
打破
}
//datarow“SetColumnError”是钩住“HasErrors”验证的对象
//以类似于IDataErrorInfo的方式。
oDR.SetColumnError(列[ColumnName],错误);
返回误差;
}
}
}
这是XAML。任何全新表单,这是窗口默认“网格”中的唯一控件

已尝试以下版本,仅定义行[0][列]

<TextBox Name="myTextBox" 
    Width="120"
    Text="{Binding  Path=Rows[0][DataName], 
                    ValidatesOnDataErrors=True,
                    UpdateSourceTrigger=PropertyChanged }" />

包括“滴滴涕”的来源,因为它对窗口是公开的

<TextBox Name="myTextBox" 
    Width="120"
    Text="{Binding  Source=DDT, Path=Rows[0][DataName], 
                    ValidatesOnDataErrors=True,
                    UpdateSourceTrigger=PropertyChanged }" />


即使是grantnz提供的建议

我认为您的xaml将源设置为字符串“DDT”,而您希望它是当前窗口上的属性DDT

是否在Visual Studio的输出窗口中看到错误,如:

System.Windows.Data Error: 40 : BindingExpression path error: 
'Rows' property not found on 'object' ''String' (HashCode=1130459074)'.
BindingExpression:Path=Rows[0][DataName]; DataItem='String' (HashCode=1130459074); 
target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')
如果将窗口DataContext设置为此(从代码DataContext=this;或),则可以使用:

     Text="{Binding  Path=DDT.Rows[0][DataName], 
                     ValidatesOnDataErrors=True,
                     UpdateSourceTrigger=PropertyChanged }" />
或者,您可以将DataContext保留为null并使用:

    <TextBox Name="myTextBox" 
     Text="{Binding  RelativeSource={RelativeSource FindAncestor, 
           AncestorType={x:Type Window}},Path=DDT.Rows[0][DataName], 
                     ValidatesOnDataErrors=True,
                     UpdateSourceTrigger=PropertyChanged }" />
如果在XAML中省略以下内容,则第二个文本框将被绑定

DataContext="{Binding RelativeSource={RelativeSource Self}}"
代码

XAML


我认为您的xaml正在将源代码设置为字符串“DDT”,而您希望它是当前窗口上的属性DDT

是否在Visual Studio的输出窗口中看到错误,如:

System.Windows.Data Error: 40 : BindingExpression path error: 
'Rows' property not found on 'object' ''String' (HashCode=1130459074)'.
BindingExpression:Path=Rows[0][DataName]; DataItem='String' (HashCode=1130459074); 
target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')
如果将窗口DataContext设置为此(从代码DataContext=this;或),则可以使用:

     Text="{Binding  Path=DDT.Rows[0][DataName], 
                     ValidatesOnDataErrors=True,
                     UpdateSourceTrigger=PropertyChanged }" />
或者,您可以将DataContext保留为null并使用:

    <TextBox Name="myTextBox" 
     Text="{Binding  RelativeSource={RelativeSource FindAncestor, 
           AncestorType={x:Type Window}},Path=DDT.Rows[0][DataName], 
                     ValidatesOnDataErrors=True,
                     UpdateSourceTrigger=PropertyChanged }" />
如果在XAML中省略以下内容,则第二个文本框将被绑定

DataContext="{Binding RelativeSource={RelativeSource Self}}"
代码

XAML


解决了,但这是一个多大的问题。。。在执行MVVM模式的示例中,大多数内容在视图模型上都有属性,这些属性公开了您想要挂接的内容。当处理到DATATABLE(或类似视图等)的绑定时,您是绑定到所述表(或视图)的列

当从任何后端查询表时,填充数据列的模式将始终强制列名为大写

因此,如果表中有一列“InvoiceTotal”,则在查询时,列名将显示为“InvoiceTotal”

如果你想把自己绑在

Path="InvoiceTotal" ... it will fail

Path="INVOICETOTAL" ... it WILL WORK
但是,如果您直接在.Net中工作(我使用C#
<Window x:Class="BindingTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">

<StackPanel>
    <TextBox 
     Text="{Binding  RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DDT.Rows[0][DataName], 
                     ValidatesOnDataErrors=True,
                     UpdateSourceTrigger=PropertyChanged }" />
    <TextBox
     Text="{Binding  Path=DDT.Rows[0][DataName], 
                     ValidatesOnDataErrors=True,
                     UpdateSourceTrigger=PropertyChanged }" />
    <TextBox
     Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=SP}" />
    </StackPanel>
</Window>
Path="InvoiceTotal" ... it will fail

Path="INVOICETOTAL" ... it WILL WORK
double SomeValue = (double)MyTable.Rows[0]["InvoiceTotal"];
or
double SomeValue = (double)MyTable.Rows[0]["INVOICETotal"];
or
double SomeValue = (double)MyTable.Rows[0]["invoicetotal"];