Telerik RadGauge + Data Binding - c#

So I'm trying to update my RadRadialGauge. It will display data (using an animated Needle) that is being retrieved on a real-time basis. I have a RadChartView that currently works by using TimeStamp and Value properties to draw the Chart. When I add a chart, sometimes I might want to add a few based on the variable I'm watching. For instance, if I want to watch Motor Speed and Output Frequency, I have to add multiple vertical axes. Part of my code to handle the data binding for the RadChartView is here:
var lineSeries = new LineSeries();
lineSeries.CategoryBinding =
new PropertyNameDataPointBinding() { PropertyName = "TimeStamp" };
lineSeries.ValueBinding =
new PropertyNameDataPointBinding() { PropertyName = "Value" };
lineSeries.ItemsSource = (chart.Chart as GuiAnalogQueue).Records;
The rest of the code is just appearance handling, and then at the end I add the LineSeries to my RadChartView.
Now, I'm trying to port this code, in a way, over to RadGauge. I'm not sure how to bind the values to the Needle so the needle moves when the Value changes.
In the XAML I've tried Value="{Binding Value}" I've tried adding binding to the ValueSource varible. Also I have done needle.Value = chart.Chart.Value;
I can't figure it out, so any help is appreciated.
UPDATE
This is what I'm trying to accomplish. My Records collection has two properties, Value and TimeStamp. I'm trying to bind my Value in the Records to the needle Value. This is my approach to do it programmatically:
public void InitializeCharts(ChartsVM charts, Theme theme)
{
DataContext = charts;
foreach (cVM chart in charts.Charts)
{
Binding value = new Binding();
value.Source = (chart.Chart as GuiAnalogQueue).Records;
value.Path = new PropertyPath("Value");
needle.SetBinding(Needle.ValueProperty, value);
}
}
However, when I do this, it is not changing the needle.Value at all. My Records is the collection that uses NotifyPropertyChanged("Records"), so I would expect my needle to change everytime Records is changed.
As you see in my original post, those three lines take care of binding the variables to ChartView charts, however I can't get the RadGauge to work.

In short, I found that Needle's don't use any type of collections for their Values. So when I tried setting up a Source to be inside of a collection, and a Path, it wasn't really liking that. Instead, I added a property right before I add the Value to the records collection (in my update values function). That way I could set my binding up as:
Binding value = new Binding();
value.Source = (chart.Chart as GuiAnalogQueue);
value.Path = new PropertyPath("AnalogValue");
needle.SetBinding(Needle.ValueProperty, value);
That reads as, the Needle will bind its Value property with the AnalogValue property that is in the Source--chart.Chart as GuiAnalogQueue.
Hope this helps if you've been directed to this page.

Here is a basic example of using the RadRadialGauge.
XAML:
<telerik:RadRadialGauge x:Name="radialGauge"
Width="300"
Height="300"
Grid.Column="0">
<telerik:RadialScale Min="1"
Max="12">
<telerik:RadialScale.Indicators>
<telerik:Needle x:Name="needle" />
<telerik:Pinpoint/>
</telerik:RadialScale.Indicators>
</telerik:RadialScale>
</telerik:RadRadialGauge>
As you can see i have a radial gauge with a radial scale defined. Radial Scale has a needle as the indicator. The RadialScale is from 1 to 12. Note that i have given a name for the needle. We will use this to push values from the code behind.
In this example i am using a dispatcher timer to tick every 1 second and i am generating a random value between 1 to 12. Here is the code behind snippets.
code snippet:
Following variables are declared at the window level
TimeSpan interval = TimeSpan.FromSeconds(1);
DispatcherTimer timer;
Random rnd = new Random();
I have defined event handlers for Window Loaded & Unloaded events. On Window Load, i start the timer.
void OnWindowLoad(object sender, RoutedEventArgs e)
{
timer = new DispatcherTimer();
timer.Interval = interval;
timer.Tick += new EventHandler(Timer_Tick);
timer.Start();
}
Here is the timer tick function:
private void Timer_Tick(object sender, EventArgs e)
{
timer.Stop();
SetNextValue();
timer.Start();
}
Here is the SetNextValue function:
private void SetNextValue()
{
int minValue = 1;
int maxValue = 12;
int nextValue = rnd.Next(minValue, maxValue);
needle.Value = nextValue;
}
In the Unloaded event handler i am stopping the timer.
void OnWindowUnload(object sender, RoutedEventArgs e)
{
timer.Stop();
}
Output:
when you run the app, you will see the needle changing its position because we are generating random numbers from 1 to 12 every second and we set the generated number to needle's value. The SetNextValue() method can be your gateway to monitoring the real value and set the needle value to that real data.
This is the basic example code i can think of to explain the radial gauge.
Hope this provides the answer you are looking for.
Update:
Here is an MVVM way of setting the needle value. Let the window implement INotifyPropertyChanged interface. Set the datacontext to the window itself
public partial class MainWindow : Window, INotifyPropertyChanged
public MainWindow()
{
InitializeComponent();
Loaded += OnWindowLoad;
Unloaded += OnWindowUnload;
DataContext = this;
}
Provide implementation for the PropertyChanged event like below:
public event PropertyChangedEventHandler PropertyChanged = delegate { };
void NotifyPropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
Implement a property called NeedleValue.
int needleValue = 1;
public int NeedleValue
{
get
{
return needleValue;
}
set
{
needleValue = value;
NotifyPropertyChanged("NeedleValue");
}
}
In the SetNextValue - just set the newly created NeedleValue property. this will fire the property changed notification.
private void SetNextValue()
{
int minValue = 1;
int maxValue = 12;
int nextValue = rnd.Next(minValue, maxValue);
NeedleValue = nextValue;
}
In the XAML bind the Needle Value property to NeedleValue like below
<telerik:Needle x:Name="needle" Value="{Binding NeedleValue}" />
Hope this provides you with the answer you are looking for :)
Lohith (Tech Evangelist, Telerik India)

Related

How to increase a ProgressBar Value according to the content of TextBoxes?

So I have 4 TextBoxes and I have already set the maximum value of my ProgressBar to 4.
ProgressAttr.Maximum = 4;
What I would like to do is increase my ProgressBar Value by 1 every time I fill out a TextBox.
My code right now looks like this:
if (!string.IsNullOrEmpty(Name_txtBox.Text))
{
ProgressAttr.Value += 1;
}
if (!string.IsNullOrEmpty(Serial_TxtBox.Text))
{
ProgressAttr.Value += 1;
}
if (!string.IsNullOrEmpty(Cap_TxtBox.Text))
{
ProgressAttr.Value += 1;
}
if (!string.IsNullOrEmpty(IDprk_TxtBox.Text))
{
ProgressAttr.Value += 1;
}
This doesn't increase the value of my ProgressBar.
I've also tried this:
if (textbox.Text.Length > 0)
{
ProgressAttr.Value += 1;
}
None of this works for me and Ive been trying to find a solution for hours. I would really appreciate your help and am looking forward to seeing solutions that you guys suggest!
I'm proposing you a method that makes use of DataBindings to synchronize the content of your TextBoxes with the Value property of a ProgressBar.
A class object can notify changes related to its Properties values implementing the INotifyPropertyChanged interface. Its public PropertyChanged event is raised to notify bound Controls that Properties of the data Provider have changed.
All bound Properties are then updated to the new values.
This allows you to have all the logic in a single place and changes to the User Interface (your Form, here) do not affect the data binding in any way.
You can add or remove Controls from the UI. The binding procedure doesn't change or needs to keep track of what has changed in the UI.
For example, bind your ProgressBar.Value property to the ProgressBarController.Value property. You initialize the ProgressBarController with the instances of the TextBox (or RichTextBox) Controls that you want to include, add a Binding to link the properties and that's all. All the rest happens automatically.
ProgressBarController pbarController = null;
// Form Constuctor
public SomeForm()
{
InitializeComponent();
// [...]
// These TextBoxes could be child of a Container (e.g., a Panel), so you could
// also get all the child Controls of this Container to build the array
var textBoxes = new[]{ Name_txtBox, Serial_TxtBox, Cap_TxtBox, IDprk_TxtBox}
ProgressAttr.Maximum = textBoxes.Length;
pbarController = new ProgressBarController(textBoxes);
ProgressAttr.DataBindings.Add("Value", pbarController, "Value", false,
DataSourceUpdateMode.OnPropertyChanged);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
pbarController.Dispose();
base.OnFormClosed(e);
}
Here, two TextBoxes already contain some text when the Form is loaded, so the ProgressBar shows a progress. If you remove all text in the Designer, of course the progress shown is initially 0:
The ProgressBarController class is initialized with the array of Controls passed in its Contructor.
► It then build a Dictionary<TextBoxBase, int> to keep track of the progress value associated to a Control: 0 if its Text is empty, otherwise 1.
TextBoxBase so you can also use RichTextBox Controls.
► The TextChanged event of these Controls is subscribes to using a single handler. The sender object will be the Control that raised the event.
► If/when the associated value has changed (the Control Text state determines a change), the PropertyChanged event is raised and the DataBinding notifies the ProgressBar to update its Value property.
► When the Parent Form is closed, call the Dispose() method of this class to remove the subscription to the TextChanged events.
using System.Runtime.CompilerServices;
private class ProgressBarController : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
private Dictionary<TextBoxBase, int> states;
private int m_Value = 0;
public ProgressBarController(params TextBoxBase[] tboxes) {
states = new Dictionary<TextBoxBase, int>();
for (int i = 0; i < tboxes.Length; i++) {
states.Add(tboxes[i], tboxes[i].Text.Length > 0 ? 1 : 0);
tboxes[i].TextChanged += TextChanged;
}
m_Value = states.Values.Sum();
}
public int Value {
get => m_Value;
private set {
if (value != m_Value) {
m_Value = value;
OnPropertyChanged();
}
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected void TextChanged(object sender, EventArgs e)
{
var tbx = sender as TextBoxBase;
int state = tbx.Text.Length > 0 ? 1 : 0;
if (states[tbx] != state) {
states[tbx] = state;
Value = states.Values.Sum();
}
}
public void Dispose() {
foreach (var tb in states.Keys) {
tb.TextChanged -= this.TextChanged;
}
}
}

Responding to object property changes within a class object hierarchy

I am developing an application which uses a hierarchical object structure and displays a few key object properties from those objects on the main GUI within a DataGridView. Those values must update when the underlying data changes. I have considered a few options:
Bind the individual DataGridView cells to the relevant object properties. I understand that this is not possible, and DGV binding is all or nothing.
Dynamically position Textboxes over the grid cells and bind those, but this seems messy.
Create an intermediate list/array/collection which references only the relevant object properties, and then use that list as a data source for the DataGridView.
Respond to the PropertyChanged events. The complication is that I have got multiple classes. The top-level object exists within the UI scope, and has a child object which in turn may have multiple child objects of its own, and so on. The UI can access properties of all objects, but not their events.
I have been looking at passing the PropertyChanged event from whichever level it occurs up the chain so that it can be handled within the UI. So within a particular class I want to respond to OnPropertyChanged within that class, and within any children, and make any events raised available to the parent class. Thus events would flow up the tree to the top.
I understand how to do the two steps individually, I think, with reference to the following:
Handling OnPropertyChanged
Pass click event of child control to the parent control
However, although I presume the two can be combined, I am not quite sure how to do this. In the UI I have got this:
project.PropertyChanged += new PropertyChangedEventHandler(ProjectPropertyChanged);
private void ProjectPropertyChanged(object sender, PropertyChangedEventArgs e) {
MessageBox.Show("In main UI. Project property changed!");
}
And then one level down I have got something like this:
public class Project : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Project() {
childObject.PropertyChanged += new PropertyChangedEventHandler(ProjectPropertyChanged);
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
ProjectPropertyChanged(sender, e); // this doesn't work due to different parameters
}
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Event available to parent class
}
}
The idea being that each class would pass its own OnPropertyChanged() events to its PropertyChanged() method, and respond to its children's OnPropertyChanged() events, and expose all to the parent class.
If doing this, ideally I would like to retain knowledge of which property changed in order to respond accordingly.
The most immediate issue is lack of compatibility between ProjectPropertyChanged and OnPropertyChanged due to different parameters. More fundamentally, though, I am not sure whether this method is workable or optimal.
How best to do this?
To answer my own question:
I tried unsuccessfully to do this with an intermediate binding source, using a DataTable (as per this question.). The problem was that I couldn't create references to the data objects. The DataTable seemed to contain values.
So I ended up using a method I was more sure about, but is less elegant, which is option 2 in my question above. I position Labels where I need bound data values, and bind to those labels. This works.
With some simplification, and pretending that our objects are animals, my solution was this:
Label[,] dashboardLabels = new Label[3,14];
private void Form1_Shown(object sender, EventArgs e)
{
CreateLabels(); // create and position labels (no binding yet)
}
public void CreateLabels(int cols = 3, int rows = 14)
{
for (int col = 0; col < cols; col++)
{
for (int row = 0; row < rows; row++)
{
// Create label...
Label l = new Label();
l.Text = "N/A";
l.ForeColor = Color.Red
dashboardLabels[col, row] = l;
this.Controls.Add(l);
// Position label over DGV cell...
Point dgvCell = dataGridView1.GetCellDisplayRectangle(col + 2, rowNumbersLabel[row], false).Location;
Point dgvGrid = dataGridView1.Location;
l.Left = dgvGrid.X + dgvCell.X;
l.Top = dgvGrid.Y + dgvCell.Y;
}
}
}
private void UpdateLabels(List<Dog> dogs)
{
for (int i = 0; i < dogs; i++)
{
if (!dashboardLabels[i, 0].Visible) dashboardLabels[i, 0].Visible = true;
if (dogs[i].IsSetUp) BindLabel(dashboardLabels[i, 0], dogs[i],"Name");
}
}
private void BindLabel(Label l, Dog dog, string observation)
{
Binding b = new Binding("Text", dog, observation);
l.DataBindings.Add(b);
l.ForeColor = Color.Green;
}
}
Then when the objects are created, I call UpdateLabels(). If not initialised, the label will show 'N/A' in red at this point. If initialised, the label will become green and will be bound to the object's name so it will update automatically from that point on.
I did much searching and the information I was finding suggested that a DataGridView does not support complex data binding i.e. it is pretty much one class to one DGV, or not at all. I couldn't find an alternative grid-like control which would do it either.

Implement INotifyPropertyChanged on a list of objects?

Hmm, not sure if I chose the right approach.
I have a grid of components. In the first column there are DatePickers.
In the second column there are combo-boxes. In the last column there are text-boxes. The grid has 15 rows.
I named them by their column and row number as you would number cells in a grid.
So dp1_1 for DatePicker are position (1,1), dp2_1 for position (2,1).
cb1_1 for ComboBox are position (1,1), cb2_1 for ComboBox position (2,1).
I keep my date pickers data, combo-boxes data, text-boxes data in an ordinary list for easy access/reference, like so:
public int numOfRows = 15;
private List<DateTime> _MyDateTimeList = new List<DateTime>();
public List<DateTime> MyDateTimeList
{
get { return _MyDateTimeList; }
set {
DateTime pomDatumObjava;
_MyDateTimeList = value;
for (int i = 0; i < numOfRows; i += 1)
{
pomDatumObjava = new DateTime();
// code for accessing/enabling/disabling the appropriate date picker, which doesn't work since I don't know how to send the window reference where my date pickers reside
// pomDatumObjava = Utils.enableDisableDatePicker(null, Constants.DP_LABEL + stringIndex, true, 1).SelectedDate.Value;
_MyDateTimeList.Add(pomDatumObjava);
}
OnPropertyChanged("MyDateTimeList");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
Console.WriteLine("OnPropertyChanged -> " + name);
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
Console.WriteLine("handler != null -> " + name);
handler(this, new PropertyChangedEventArgs(name));
}
}
public static DatePicker enableDisableDatePicker(System.Windows.Window myWindow, string name, bool enableDisable, double op)
{
DatePicker dp = (DatePicker)myWindow.FindName(name);
if (!enableDisable)
{
dp.SelectedDate = null;
}
dp.IsEnabled = enableDisable;
dp.Opacity = op;
return dp;
}
How do I access my components in the window and reference them appropriately so that each time I change a value in certain DatePicker, I detect the change in the list?
You can find the Utils function in comments line. Where it says null, there should be the window objects where my components are placed.
Or, is this the right approach?
I will have lot of components(15x3 = 45 x code for OnPropertyChanged), so the MVVM file will be quite large to set OnPropertyChanged() for all of them.
As ASh says, you need an ObservableCollection of objects, one for each row. ObservableCollections automatically update their bound controls when you add or remove objects, and pass on events when the objects change. These objects would presumably have three properties (for the datepicker, combobox and text box) that have OnPropertyChanged().
Then bind the ObservableCollection to the ItemSource of your grid, and the three controls to the three properties of an item.
For MVVM, you shouldn't ever need to reference a control in the View. Instead the view should reflect the state of the ViewModel. If you want to disable a datepicker, it's Enabled property should be bound to some thing that raises OnPropertyChanged().
If you post your view, we can suggest how to do this.

C# - WPF - Prevent an update of a bound focused TextBox

I have a TextBox in a Windows Desktop WPF application bound to a property of a ViewModel. Now the user focuses the TextBox and starts entering a new value. During this time a background process gets a new Value for the same Property (e.g. because another user in a multi user environment enters a new value and an observer is detecting and propagating this change) and calls a PropertyChanged event for this Property. Now the value changes and the stuff the current user just entered is lost.
Is there a built in way to prevent the change while the TextBox is focused? Or do I have to build my own solution?
I think a custom control is needed to achieve the behavior you describe. By overriding a couple methods on the default WPF TextBox, we can keep the user input even if the View Model changes.
The OnTextChanged method will be called regardless of how our textbox is updated (both for keyboard events and View Model changes), but overriding the OnPreviewKeyDown method will separate out direct user-input. However, OnPreviewKeyDown does not provide easy access to the textbox value because it is also called for non-printable control characters (arrow keys, backspace, etc.)
Below, I made a WPF control that inherits from TextBox and overrides the OnPreviewKeyDown method to capture the exact time of the last user key-press. OnTextChanged checks the time and updates the text only if both events happen in quick succession.
If the last keyboard event was more than a few milliseconds ago, then the update probably did not happen from our user.
public class StickyTextBox : TextBox
{
private string _lastText = string.Empty;
private long _ticksAtLastKeyDown;
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
_ticksAtLastKeyDown = DateTime.Now.Ticks;
base.OnPreviewKeyDown(e);
}
protected override void OnTextChanged(TextChangedEventArgs e)
{
if (!IsInitialized)
_lastText = Text;
if (IsFocused)
{
var elapsed = new TimeSpan(DateTime.Now.Ticks - _ticksAtLastKeyDown);
// If the time between the last keydown event and our text change is
// very short, we can be fairly certain than text change was caused
// by the user. We update the _lastText to store their new user input
if (elapsed.TotalMilliseconds <= 5) {
_lastText = Text;
}
else {
// if our last keydown event was more than a few seconds ago,
// it was probably an external change
Text = _lastText;
e.Handled = true;
}
}
base.OnTextChanged(e);
}
}
Here's a sample View Model which I used for testing. It updates its own property 5 times from a separate thread every 10 seconds to simulate a background update from another user.
class ViewModelMain : ViewModelBase, INotifyPropertyChanged
{
private delegate void UpdateText(ViewModelMain vm);
private string _textProperty;
public string TextProperty
{
get { return _textProperty; }
set
{
if (_textProperty != value)
{
_textProperty = value;
RaisePropertyChanged("TextProperty");
}
}
}
public ViewModelMain()
{
TextProperty = "Type here";
for (int i = 1; i <= 5; i++)
{
var sleep = 10000 * i;
var copy = i;
var updateTextDelegate = new UpdateText(vm =>
vm.TextProperty = string.Format("New Value #{0}", copy));
new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(sleep);
updateTextDelegate.Invoke(this);
}).Start();
}
}
}
This XAML creates our custom StickyTextBox and a regular TextBox bound to the same property to demonstrate the difference in behavior:
<StackPanel>
<TextBox Text="{Binding TextProperty, UpdateSourceTrigger=PropertyChanged}" Margin="5"/>
<TextBlock FontWeight="Bold" Margin="5" Text="The 'sticky' text box">
<local:StickyTextBox Text="{Binding TextProperty}" MinWidth="200" />
</TextBlock>
</StackPanel>

Issue with property not passing back value to text box on property change

I am working on a WPF application and i have a textbox bound (bidirectionally) to a property in my view model.
I am trying to prevent a user from typing more than 100 characters into this textbox (this is the max the database will store) so i have written this.
public abstract class AppBaseViewModel : ViewModelBase
{
private String _text;
public String Text
{
get { return _text; }
set
{
_text = CheckTextLength(value, _text);
OnPropertyChanged("Text");
}
}
private string CheckTextLength(string value, string text)
{
if (value.Length < 100)
{
return value;
}
else
{
return text;
}
}
}
All this code seems to do is save the first 100 characters to the field but it still allows the user to carry on typing past 100 characters... i would guess it is because the field value isn't being passed back to the textbox.
I don't understand why this doesn't work as i did something similar using MVVM Light's RaisePropertyChange() in a different application.
It is worth noting that i am unable to access the designer for the textbox so cannot set the .Net textbox property for max length.
Edit: Just for clarification i cannot view or edit the xaml as some are suggesting as i do not have access to the XAML file (i know, it's stupid). All the bindings we use are two way by default
Have you tried with TextBox.MaxLength ?
<TextBox MaxLength="100"/>
Gets or sets the maximum number of characters that can be manually entered into the text box.
If no access to the XAML, eventually get access to the XAML instead of parsing and verifying lengths of arrays and use substrings here and there. At least that's what i would do for this simple issue or talk to the designer to add that small piece of code.
Update 1
public static T GetChildOfType<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) return null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var result = (child as T) ?? GetChildOfType<T>(child);
if (result != null) return result;
}
return null;
}
Go and get that child and set its MaxLength. This is just a slight modification on the View so it will not affect the MVVM pattern.
OK. I'm not at all sure that I'm proud of this, but am presenting it as an alternative.
You can change the UpdateSourceTrigger of the TextBox's Text property by applying a universal Style to all of the TextBoxes. This is only going to be practical in pretty weird arrangements, but the question is a little unusual in itself.
XAML codebehind:
//I'm using MVVM Light here - you need to be able to find an instance
//of your AppBaseViewModel somehow.
private ViewModelLocator _locator;
//View codebehind constructor, may need to change names as appropriate
public AppBaseView()
{
InitializeComponent();
//MVVM Light again
_locator = new ViewModelLocator();
//Create the binding
Binding binding = new Binding();
//Source = The instance of your ViewModel
binding.Source = _locator.AppBaseViewModel ;
binding.Path = new PropertyPath("Text");
binding.Mode = BindingMode.TwoWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
//Create a Style with no Key - this will apply to *all* TextBoxes
//without their own explicit Style set.
Style style = new Style(typeof(TextBox));
style.Setters.Add(new Setter(TextBox.TextProperty, binding));
//Add the Style to the XAML's Resources:
Resources.Add(typeof(TextBox), style);
}
The view won't listen to the PropertyChanged notification if it's currently trying to change the property itself.
The only thing that comes to mind is launching an extra delayed PropertyChanged notification when you detect the constraint is not met...
private string CheckTextLength(string value, string text)
{
if (value.Length < 100)
{
return value;
}
else
{
MyDispatcher.BeginInvoke(new Action(() =>
OnPropertyChanged("Text")),
DispatcherPriority.Loaded);
return text;
}
}
Can't try the code, so sorry if it doesn't build righ away. MyDispatcher could be your Application.Current.Dispatcher, for instance.
The xaml view /the binding is only updated when the textbox has lost focus. if the text entered is <100 then the value is set otherwise _text is set. this means that initially _text has no value so null will be set upon the if statement being false. i also suggest yo use RaisePropertyChanged(); and when used within the property itself no parameter is needed.

Categories