Reputation: 2646
I would like to bind a property in a class one-way to a textbox. but having am trouble, the scenerio is in my code below, getting the string value of test_string into my view. This code I have tried but doesn't seem to work. What do I need to do?
Class with property:
namespace config
{
class tester : INotifyPropertyChanged
{
public tester()
{
}
private string test_string;
public string Test{
get { return test_string; }
private set
{
test_string = value;
RaisePropertyChanged("Test");
}
}
public void dotest(){
... do some testing
Test = "Past point one"
... do some more testing
Test += "Past point two"
... do some more testing
Test += "Finished testing"
}
}
}
ViewModel
using config
namespace notif
{
class t_viewmodel
{
public t_viewmodel()
{
}
Tester tester = new Tester();
public string TestLink
{
get { return tester.Test; }
}
public void run_test()
{
tester.dotest();
}
}
}
View
<Window x:Class="notif.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="263" Width="539"
xmlns:viewmodel="clr-namespace:notif" >
<Window.DataContext>
<viewmodel:t_viewmodel/>
</Window.DataContext>
<Grid>
<TextBox Name="txtTestMessage" Text="{Binding TestLink}" />
<Button Content="Do Test" Name="button1" />
<!--Pretending the button it goes to viewmodels run_test()-->
</Grid>
</Window>
[EDIT1]
As the process is running through dotest, it is not until it has finished that the textbox gets populated, is there something I can do to have this update each time the Test property is set?
[EDIT2] Altered
public void SQLDBAccessTest(string db)
{
if (test_debug)
ConnectionTest = "Test started. " + DateTime.Now;
string conn_string = "";
try
{
conn_string = createConnectionString(db);
if (test_debug)
ConnectionTest += "\nConnection string = '" + conn_string + "'";
}
catch (Exception ex)
{
throw ex;
}
try
{
if (test_debug)
ConnectionTest += "\nCreating connection to database...";
cnn = new SqlConnection(conn_string);
if (test_debug)
ConnectionTest += "\nConnection created.";
if (test_debug)
ConnectionTest += "\nEstablishing open connection to database...";
cnn.Open();
if (test_debug)
ConnectionTest += "\nEstablished connection to database.";
if (test_debug)
ConnectionTest += "\nClosing connection to database...";
cnn.Close();
if (test_debug)
ConnectionTest += "\nConnection closed.";
}
catch (Exception ex)
{
if (test_debug)
ConnectionTest += "\nAn error has occured whilst connecting to the database.\n\t - " + ex.Message;
throw ex;
}
if (test_debug)
ConnectionTest += "\nTest complete. " + DateTime.Now;
}
private string createConnectionString(string db)
{
string tempConString = ConStr;
try
{
TestConnSettingsFile();
setDBDataSourceAndSecurity();
if (test_debug)
ConnectionTest += "\nCreating connection string...";
tempConString = tempConString.Replace("<SERVER>", db_datasource);
tempConString = tempConString.Replace("<DB>", db);
tempConString = tempConString.Replace("<SECURITY>", db_security);
if (test_debug)
ConnectionTest += "\nCreated connection string.";
}
catch (Exception ex)
{
throw ex;
}
return tempConString;
}
private bool TestConnSettingsFile()
{
bool settingsFileExist = false;
string filePath = "";
if (test_debug)
ConnectionTest += "\nTesting for encrypted connection file...";
try
{
string directory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
filePath = System.IO.Path.Combine(directory, "afx.settings");
if (System.IO.File.Exists(filePath))
{
settingsFileExist = true;
xmlSettingsFilePath = filePath;
if (test_debug)
ConnectionTest += "\nThe encrypted connection file has been found at: " + filePath;
}
else
{
if (test_debug)
ConnectionTest += "\nThe encrypted connection file could not be found at: " + filePath;
throw new Exception("The encrypted connection file could not be found at: " + filePath);
}
}
catch (Exception ex)
{
if (test_debug)
ConnectionTest += "\nError occured while testing if encrypted file exists:\n\t - " + ex.Message;
throw ex;
}
return settingsFileExist;
}
private bool setDBDataSourceAndSecurity()
{
bool result = false;
if (test_debug)
ConnectionTest += "\nRetrieving encrypted connection...";
try
{
if (System.IO.File.Exists(xmlSettingsFilePath))
{
XmlTextReader reader = null;
if (test_debug)
ConnectionTest += "\nReading connection xml file...";
// Load the file with an XmlTextReader
reader = new XmlTextReader(xmlSettingsFilePath);
// Read the File
while (reader.Read())
{
//checking where read text is element and and name is “DataSource”
if (reader.NodeType == XmlNodeType.Element && reader.Name == "DataSource")
{
if (test_debug)
ConnectionTest += "\nReading data source...";
//assigning ReadElementstring to strCmb1.
string datasource = reader.ReadElementString();
if (test_debug)
ConnectionTest += "\nData source = " + db_datasource;
}
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Security")
{
if (test_debug)
ConnectionTest += "\nReading security...";
string security = reader.ReadElementString();
if (test_debug)
ConnectionTest += "\nSecurity = " + db_security;
}
}
if (test_debug)
ConnectionTest += "\nClosing connection xml file...";
reader.Close();
reader = null;
if (test_debug)
ConnectionTest += "\nSuccess retrieving encrypted connection...";
result = true;
}
else
{
if (test_debug)
ConnectionTest += "\nLost connection xml file, could not be found at: " + xmlSettingsFilePath;
throw new Exception("The configuration file, setup for database connectivity could not be found.");
}
}
catch (Exception ex)
{
if (test_debug)
ConnectionTest += "\nError occured while setting data source and security:\n\t - " + ex.Message;
throw ex;
}
return result;
}
Upvotes: 2
Views: 3197
Reputation: 102793
The property you're binding to is TestLink
, which is not notifying its change. Instead, you could expose the Tester
instance itself:
public string Tester
{
get { return tester; }
}
Now you can simply bind to Tester.Test
-- that does get the change notifications:
<TextBox Name="txtTestMessage" Text="{Binding Tester.Test}" />
Edit
To update the UI continuously with long-running tasks, you'll need to use background threads. The UI updates (ie, setting "Test") need to be dispatched back to the UI thread. Here's an example:
public void dotest(){
var dummyAction = new Action( () => Thread.Sleep(1000) );
var first = new Task(dummyAction);
var second = new Task(dummyAction);
var third = new Task(dummyAction);
first.ContinueWith(task =>
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
Test = Environment.NewLine + "past point one";
}));
second.Start();
});
second.ContinueWith(task =>
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
Test += Environment.NewLine + "past point two";
}));
third.Start();
});
third.ContinueWith(task => {
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
Test += Environment.NewLine + "Finished testing";
}));
});
first.Start();
}
Upvotes: 1
Reputation: 1221
In your text box you bind TestLink
property, but it will not notify property change. instead of that you need to bind Test
property of Tester
.
Tester tester = new Tester();
//Add property to return your Tester instance.
public Tester TestLink
{
get { return tester; }
}
//In your XAML bind Test property.
<TextBox Name="txtTestMessage" Text="{Binding TestLink.Test}" />
Upvotes: 1