縮小解決方案
我非常接近,但不知道如何申請XAML來改變datacontext的價值。如有需要,請回顧下面的原始問題。WPF綁定的DataTable行列到文本框
我的問題是,我有一個ViewModel類作爲datacontext到一個窗口。在這個視圖模型上,我有一個「DataTable」對象(帶有列,只有一行用於測試)。當我嘗試將文本框「TEXT」綁定到數據表的列時,它不起作用。我最終發現的是,無論我給它什麼「源」或「路徑」,它都不會合作。但是,只是通過玩弄場景,我說了它。我們看看吧。 Textbox控件具有自己的「DataContext」屬性。因此,在代碼中,我只是強制使用textbox.DataContext =「MyViewModel.MyDataTableObject」,並將路徑保留爲僅代表「MyDataColumn」的列,並且工作正常。因此,那麼,我將如何編寫用於文本框控件的XAML,以便將「DataContext」屬性設置爲視圖模型窗口的數據表對象的窗口,但無法得到正確的結果。例如:
<TextBox Name="myTextBox"
Width="120"
DataContext="THIS IS WHAT I NEED" --- to represent
Text="{Binding Path=DataName,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged }" />
的DataContext這個文本應反映以下XAML的細節並得到
(ActualWindow)(DDT =視圖模型)(oPerson =數據表是存在於視圖模型) CurrentWindow.DDT.oPerson
我卡上的東西用結合。我想要將一個數據表的列綁定到一個文本框控件。聽起來很簡單,但我錯過了一些東西。首先簡單的情況。如果我有我的窗口並將數據上下文設置爲「MyDataTable」的數據上下文,並且具有文本框PATH = MyDataColumn,則一切正常,沒有問題,包括數據驗證(錯誤的紅色邊框)。
現在,問題所在。如果我在我的窗口類中直接使用與公共相同的「MyDataTable」(但是如果我在實際的ViewModel對象上有相同的東西,但是簡化了水平引用的窗口),我無法從它工作直接的XAML源代碼。我知道我必須設置「SOURCE = MyDataTable」,但是列的路徑不起作用。
<TextBox Name="myTextBox"
Text="{Binding Source=DDT, Path=Rows[0][DataName],
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged }" />
然而,從其他測試,如果我設置的路徑(代碼隱藏),以
object txt = FindName("myTextBox");
Binding oBind = new Binding("DataName");
oBind.Source = DDT;
oBind.Mode = BindingMode.TwoWay;
oBind.ValidatesOnDataErrors = true;
oBind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
((TextBox)txt).SetBinding(TextBox.TextProperty, oBind);
它的工作(當數據表可作爲公共窗口(或視圖模型))
我是什麼都不知道。
更新:這裏是我在這裏申請的示例代碼的完整發布。
using System.ComponentModel;
using System.Data;
namespace WPFSample1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public DerivedDataTable DDT;
public MainWindow()
{
InitializeComponent();
// hook up to a Data Table
DDT = new DerivedDataTable();
DataContext = this;
// with THIS part enabled, the binding works.
// DISABLE this IF test, and binding does NOT.
// but also note, I tried these same settings manually via XAML.
object txt = FindName("myTextBox");
if(txt is TextBox)
{
Binding oBind = new Binding("DataName");
oBind.Source = DDT;
oBind.Mode = BindingMode.TwoWay;
oBind.ValidatesOnDataErrors = true;
oBind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
((TextBox)txt).SetBinding(TextBox.TextProperty, oBind);
}
}
}
// Generic class with hooks to enable error trapping at the data table
// level via ColumnChanged event vs IDataErrorInfo of individual properties
public class MyDataTable : DataTable
{
public MyDataTable()
{
// hook to column changing
ColumnChanged += MyDataColumnChanged;
}
protected void MyDataColumnChanged(object sender, DataColumnChangeEventArgs e)
{ ValidationTest(e.Row, e.Column.ColumnName); }
// For any derived datatable to just need to define the validation method
protected virtual string ValidationTest(DataRow oDR, string ColumnName)
{ return ""; }
}
public class DerivedDataTable : MyDataTable
{
public DerivedDataTable()
{
// simple data table, one column, one row and defaulting the value to "X"
// so when the window starts, I KNOW its properly bound when the form shows
// "X" initial value when form starts
Columns.Add(new DataColumn("DataName", typeof(System.String)) );
Columns["DataName"].DefaultValue = "X";
// Add a new row to the table
Rows.Add(NewRow());
}
protected override string ValidationTest(DataRow oDR, string ColumnName)
{
string error = "";
switch (ColumnName.ToLower())
{
case "dataname" :
if ( string.IsNullOrEmpty(oDR[ColumnName].ToString())
|| oDR[ColumnName].ToString().Length < 4)
error = "Name Minimum 4 characters";
break;
}
// the datarow "SetColumnError" is what hooks the "HasErrors" validation
// in similar fashion as IDataErrorInfo.
oDR.SetColumnError(Columns[ColumnName], error);
return error;
}
}
}
而這裏的XAML。任何全新的窗體,這是窗口默認「網格」中的唯一控件。
嘗試以下版本,只是定義行[0] [專欄]
<TextBox Name="myTextBox"
Width="120"
Text="{Binding Path=Rows[0][DataName],
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged }" />
包括 「DDT」 的來源,因爲它是公衆對窗口
<TextBox Name="myTextBox"
Width="120"
Text="{Binding Source=DDT, Path=Rows[0][DataName],
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged }" />
甚至建議提供通過grantnz
Grantnz,不,我不是在暴食得到任何錯誤。我試過你的路徑= DDT.Rows [0] [DataName],這是不成功的。我試圖包括RelativeSource/FindAncestor也沒有工作。感謝您的建議,但。 – DRapp 2012-04-29 12:05:25
@DRapp - 您是否在配置綁定之前或之後設置了DDT?如果您是從窗口構造函數中的代碼設置它,請嘗試將代碼移到InitializeComponent()上面。 (或實現INotifyPropertyChanged)。 – grantnz 2012-04-29 20:27:24
@DRapp - 我很驚訝你在輸出窗口中看不到任何綁定錯誤。如果你故意發生錯誤會發生什麼(例如Path = PropertyThatDoesntExist)? – grantnz 2012-04-29 20:39:52