WPF将Textbox绑定到另一个类中的数据集

WPF将Textbox绑定到另一个类中的数据集,wpf,textbox,dataset,Wpf,Textbox,Dataset,WPF通常不是我的领域,所以我是一个有点新手,我在想如何在WPF中实现一些东西时遇到了一些困难,而在WinForms中这是小菜一碟。我似乎在这个论坛上找不到正确的线索,也找不到正确的YouTube教程来引导我找到答案。我在将简单的数据绑定到WPF文本框时遇到问题,无法正常工作。我试图实现的行为是,对文本框所做的任何更改都会立即反映在源类数据集中。这是一个简单的显示/编辑场景,我相信有一个非常简单的答案 这就是我在WinForms中所做的 表格代码: public partial class Fo

WPF通常不是我的领域,所以我是一个有点新手,我在想如何在WPF中实现一些东西时遇到了一些困难,而在WinForms中这是小菜一碟。我似乎在这个论坛上找不到正确的线索,也找不到正确的YouTube教程来引导我找到答案。我在将简单的数据绑定到WPF文本框时遇到问题,无法正常工作。我试图实现的行为是,对文本框所做的任何更改都会立即反映在源类数据集中。这是一个简单的显示/编辑场景,我相信有一个非常简单的答案

这就是我在WinForms中所做的

表格代码:

public partial class Form1 : Form
{
    private DATARECORD CURRENTUSER;

    public Form1()
    {
        InitializeComponent();
        CURRENTUSER = new DATARECORD(@"Data Source=C:\Users\rr187718\Documents\Personal\Programming\DynamicBackup\DynamicBackup\bin\Debug\Data\dbData.sdf");
        CURRENTUSER.FncBind(CtlCopiesToKeep, "Value", "tblUser.CopiesToKeep");
    }

    //Test code to display the value in the DataSet
    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show(CURRENTUSER.copiesToKeep.ToString());
    }
}
public class DATARECORD
{
    private string ConnectionString;
    private DataSet CurrentRecord;
    public int copiesToKeep { get { return Int32.Parse(CurrentRecord.Tables["tblUser"].Rows[0]["CopiesToKeep"].ToString()); } }

    public DATARECORD(string connectionString)
    {
        ConnectionString = connectionString;
        CurrentRecord = new DataSet();
        SQL SQL = new SQL(2);
        DataTable userTable = SQL.fncSelectAsTable(ConnectionString, "tblUser", "USERID=2");
        userTable.TableName = "tblUser";
        CurrentRecord.Tables.Add(userTable);
        userTable.Dispose();
    }

    public void FncBind(Control c, string type, string field)
    {
        c.DataBindings.Add(type, CurrentRecord, field, true, DataSourceUpdateMode.OnPropertyChanged);
    }
}
类别代码:

public partial class Form1 : Form
{
    private DATARECORD CURRENTUSER;

    public Form1()
    {
        InitializeComponent();
        CURRENTUSER = new DATARECORD(@"Data Source=C:\Users\rr187718\Documents\Personal\Programming\DynamicBackup\DynamicBackup\bin\Debug\Data\dbData.sdf");
        CURRENTUSER.FncBind(CtlCopiesToKeep, "Value", "tblUser.CopiesToKeep");
    }

    //Test code to display the value in the DataSet
    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show(CURRENTUSER.copiesToKeep.ToString());
    }
}
public class DATARECORD
{
    private string ConnectionString;
    private DataSet CurrentRecord;
    public int copiesToKeep { get { return Int32.Parse(CurrentRecord.Tables["tblUser"].Rows[0]["CopiesToKeep"].ToString()); } }

    public DATARECORD(string connectionString)
    {
        ConnectionString = connectionString;
        CurrentRecord = new DataSet();
        SQL SQL = new SQL(2);
        DataTable userTable = SQL.fncSelectAsTable(ConnectionString, "tblUser", "USERID=2");
        userTable.TableName = "tblUser";
        CurrentRecord.Tables.Add(userTable);
        userTable.Dispose();
    }

    public void FncBind(Control c, string type, string field)
    {
        c.DataBindings.Add(type, CurrentRecord, field, true, DataSourceUpdateMode.OnPropertyChanged);
    }
}
然后在主窗体上有一个名为“CtlCopiesToKeep”的简单文本框和一个“test”按钮

有人知道一个好的,简单的例子,可以说明如何做到这一点吗

多谢各位, 戴夫

编辑:

你好,诺尔。非常感谢您花时间解释这一切。我已经把它放在一起了,但是绑定似乎有问题,因为当我更改文本框中的值时,它不会更新数据集。下面是代码和XAML。如果有人能给我指出正确的方向,我将不胜感激

更新的主代码

public partial class MainWindow : Window
{
    public DATARECORD SELECTEDUSER;
    private string ConnectionString = @"Data Source=C:\Users\rr187718\Documents\Personal\Programming\DynamicBackup\DynamicBackup\bin\Debug\Data\dbData.sdf";

    public MainWindow()
    {
        InitializeComponent();
        SELECTEDUSER = new DATARECORD(ConnectionString);
        GrdMain.DataContext = SELECTEDUSER; 
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        SELECTEDUSER.fncShowVals("BasePath");
    }
}
public class DATARECORD : INotifyPropertyChanged
{
    private string ConnectionString;
    private DataSet currentRecord = new DataSet();
    private string BasePath = null;

    public string basePath
    {
        get
        {
            return currentRecord.Tables["tblStorage"].Rows[0]["BasePath"].ToString() ;
        }
        set
        {
            BasePath = value;
            OnPropertyChanged("BasePath");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public DATARECORD(string connectionString)
    {
        ConnectionString = connectionString;
        SQL SQL = new SQL(ConnectionString, SQLVersion.CE);
        DataTable storageTable = SQL.fncSelectAsTable(ConnectionString, "tblStorage", "USERID=2");
        storageTable.TableName = "tblStorage";
        currentRecord.Tables.Add(storageTable);
        storageTable.Dispose();  
    }

    public void fncShowVals(string test)
    {
        MessageBox.Show(currentRecord.Tables["tblStorage"].Rows[0][test].ToString());
    }

    protected void OnPropertyChanged(string value)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(value));
        }
    }

}
更新的班级代码

public partial class MainWindow : Window
{
    public DATARECORD SELECTEDUSER;
    private string ConnectionString = @"Data Source=C:\Users\rr187718\Documents\Personal\Programming\DynamicBackup\DynamicBackup\bin\Debug\Data\dbData.sdf";

    public MainWindow()
    {
        InitializeComponent();
        SELECTEDUSER = new DATARECORD(ConnectionString);
        GrdMain.DataContext = SELECTEDUSER; 
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        SELECTEDUSER.fncShowVals("BasePath");
    }
}
public class DATARECORD : INotifyPropertyChanged
{
    private string ConnectionString;
    private DataSet currentRecord = new DataSet();
    private string BasePath = null;

    public string basePath
    {
        get
        {
            return currentRecord.Tables["tblStorage"].Rows[0]["BasePath"].ToString() ;
        }
        set
        {
            BasePath = value;
            OnPropertyChanged("BasePath");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public DATARECORD(string connectionString)
    {
        ConnectionString = connectionString;
        SQL SQL = new SQL(ConnectionString, SQLVersion.CE);
        DataTable storageTable = SQL.fncSelectAsTable(ConnectionString, "tblStorage", "USERID=2");
        storageTable.TableName = "tblStorage";
        currentRecord.Tables.Add(storageTable);
        storageTable.Dispose();  
    }

    public void fncShowVals(string test)
    {
        MessageBox.Show(currentRecord.Tables["tblStorage"].Rows[0][test].ToString());
    }

    protected void OnPropertyChanged(string value)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(value));
        }
    }

}
文本框的XAML

<Window x:Class="WpfBind.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">
<Grid Name="GrdMain">
    <TextBox Text="{Binding basePath, Mode=TwoWay, UpdateSourceTrigger =PropertyChanged}" Height="23" HorizontalAlignment="Left" Margin="124,70,0,0" Name="CtlBaseFolder" VerticalAlignment="Top" Width="120" />
    <Label Content="BaseFolder" Height="28" HorizontalAlignment="Left" Margin="41,69,0,0" Name="label2" VerticalAlignment="Top" />
    <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="263,142,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
谢谢你,戴夫

更新-2015年4月2日-2

你好,Noel,我已经应用了你的代码,但不幸的是它仍然不能工作(如果我点击“测试”按钮,数据集不会反映文本框中的更改)。这是全部代码。顺便说一句,我非常感谢你在这方面花时间,非常感谢

    public partial class MainWindow : Window
{
    private string ConnectionString = @"Data Source=C:\Users\rr187718\Documents\Personal\Programming\DynamicBackup\DynamicBackup\bin\Debug\Data\dbData.sdf";
    private readonly DATARECORD _data = null;
    public DATARECORD Data
    {
        get
        {
            return _data;
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        _data = new DATARECORD(ConnectionString);
        DataContext = Data; //All controls connected to this class will now look for their value in 'Data' (DataContext inherits and must be a property because you can only bind to properties)

    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Data.fncShowVals("BasePath");
    }
}

public class DATARECORD : INotifyPropertyChanged
{
    private string ConnectionString;
    private DataSet currentRecord = new DataSet();

    private string ___basePath = null;
    private string _basePath
    {
        get
        {
            if (___basePath == null)
            {
                //We only access the currentRecord if we did not yet stored the value
                //   otherwise it would read the currentRecord every time you type a char 
                //   in the textbox.
                //   Also: Pay attention to multiple possible NullReferenceExceptions and IndexOutOfBoundsExceptions
                ___basePath = currentRecord.Tables["tblStorage"].Rows[0]["BasePath"].ToString();
            }

            return (___basePath == String.Empty) ? null : ___basePath;
        }
        set
        {
            ___basePath = (value == null) ? String.Empty : value;
            NotifyPropertyChanged("BasePath");
        }
    }

    protected void PushBasePathToDataBase()
    {
        //Save the value of ___basePath to the database
    }

    public string BasePath
    { //The Binding recieves/sets the Data from/to this property
        get
        {
            return _basePath;
        }
        set
        {
            _basePath = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public DATARECORD(string connectionString)
    {
        ConnectionString = connectionString;
        SQL SQL = new SQL(ConnectionString, SQLVersion.CE);
        DataTable storageTable = SQL.fncSelectAsTable(ConnectionString, "tblStorage", "USERID=2");
        storageTable.TableName = "tblStorage";
        currentRecord.Tables.Add(storageTable);
        storageTable.Dispose();
        ___basePath = currentRecord.Tables["tblStorage"].Rows[0]["BasePath"].ToString();
    }

    public void fncShowVals(string test)
    {
        MessageBox.Show(currentRecord.Tables["tblStorage"].Rows[0][test].ToString());

    }

    protected void NotifyPropertyChanged(string PropertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
    }
}

使用绑定将数据与视觉效果分离是一件好事。因为这在winforms中是不可能的。要使绑定正常工作,必须执行以下操作:

  • textBox必须将其DataContext设置为包含绑定值的类的实例<代码>数据上下文=MyDataInstance您可以在文本框本身或任何父项上设置

  • 要绑定的值和DataContext必须是公共属性。F.e.:

    私有字符串_name=null

    公共字符串名称{
    得到{
    返回_name;
    }
    设置{
    _名称=值;
    NotifyPropertyChanged(“名称”);
    }
    }

  • 数据类必须实现
    INotifyPropertyChanged

如果设置完毕,您可以用xaml编写文本框:

<TextBlock Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
在这段代码中,您现在应该认识到设置
ThisIsAwesome
\u ThisIsAwesome
都将更新绑定。但是要小心设置
。\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。
ThisIsAwesome的setter当前不可用(无论什么原因),这就是我添加受保护属性的原因。你明白我想用它实现什么吗

EDIT2(因为您的代码仍然无法工作)

最后是主窗口xaml中的文本框:

<TextBlock Text="{Binding BasePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>


你能发布你的XAML吗?谢谢Noel,我已经进一步发布了新代码和XAML。我将感谢您的想法,如何使装订100%的工作。再次非常感谢,Dave@the_cat21传入OnPropertyChanged()的项目名称区分大小写,“basepath”与“basepath”不同。请确保字符串与属性的名称相等,否则UI将不会对其进行操作。_cat21将我的答案扩展了很多Hello Noel,再次感谢您的详细解释。我理解您所说的原则,并且您的代码策略非常符合逻辑。不过,请看我的“编辑”到原来的职位。我不明白底层数据集的值如何符合这个等式。非常感谢,戴夫。@U cat21见编辑。我猜你的dataContext不是一个属性?无论如何,我也做了一些性能改进。。。