Setting Datacontext from codebehind confusion
-
Thursday, August 02, 2012 3:21 PM
Hi,
I am using the following line in codebehind to create textbox and its text is binded as well.
foreach( TextBoxData textData in textBoxDataList )
{
ShowTextBox( textData );
}private void ShowTextBox( TextBoxData textData )
{
//Create a new TextBox
TextBox setupText = new TextBox();
setupText.Tag = textData;
//setupText.Text = textData.CurrentValue;
setupText.DataContext = textData;
Binding binding = new Binding( );
binding.Source = textData.CurrentValue;
binding.Mode = BindingMode.OneWay;
binding.UpdateSourceTrigger =
UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding( setupText,
TextBox.TextProperty, binding );
}I also implement notifypropertychanged in the page and notify the property inside TextBoxData. Actually its "CurrentValue" inside TextBoxData class. in the page i am holding list<TextBoxData> . the problem i am facing is the propertychanged event of inotifychanged is always null. but the textdata currentvalue get changed. so it sis not get updating in UI.
So my assumption is i am setting the datacontext as wrong??? How can i check it?
All Replies
-
Thursday, August 02, 2012 3:39 PMModerator
The devil is in the detail. If you could show us a complete example, we could point out where the problem is.
To try and help, I give a complete example of what I think you want:
MainWindow.xaml.cs
using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Collections.ObjectModel; using System.ComponentModel; namespace ThemesExample { public partial class MainWindow : Window { public ObservableCollection<TextBoxData> textBoxDataList { get; set; } public MainWindow() { InitializeComponent(); textBoxDataList = new ObservableCollection<TextBoxData> { new TextBoxData { CurrentValue = 1}, new TextBoxData { CurrentValue = 2}, }; foreach( TextBoxData textData in textBoxDataList ) { ShowTextBox( textData ); } } private void ShowTextBox(TextBoxData textData) { TextBox setupText = new TextBox(); setupText.Tag = textData; setupText.DataContext = textData; Binding binding = new Binding("CurrentValue"); binding.Source = textData; //binding.Mode = BindingMode.OneWay; binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; //BindingOperations.SetBinding(setupText, TextBox.TextProperty, binding); setupText.SetBinding(TextBox.TextProperty, binding); MyButtons.Children.Add(setupText); } public class TextBoxData : INotifyPropertyChanged { int _CurrentValue; public int CurrentValue { get { return _CurrentValue; } set { if (_CurrentValue != value) { _CurrentValue = value; RaisePropertyChanged("CurrentValue"); } } } void RaisePropertyChanged(string prop) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); } public event PropertyChangedEventHandler PropertyChanged; } } }MainWindow.xaml
<Window x:Class="ThemesExample.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"> <StackPanel x:Name="MyButtons" /> </Window>You can put breakpoints on the getter and setter of CurrentValue and you will see it working as expected.
You can also fiddle with the values code-side and they will be updated in the UI. The key here is to have INotifyPropertyChanged on the properties themselves. I wasn't sure what you meant about "INotifyPropertyChanged at page level", when it is the properties of this class that you want to watch, not the page or collection they come from.
Also, you had Mode=OneWay, which means you won't get user changes going back to the original class, is that what you wanted?
Would a TextBlock or Label do better if that is the case?
In my example I have left it as default for the TextBox TextProperty, which is TwoWay.Regards,
Pete
#PEJL
- Edited by XAML guyMicrosoft Community Contributor, Moderator Thursday, August 02, 2012 3:41 PM
- Marked As Answer by Ajin Prasad Monday, August 06, 2012 4:42 PM
-
Thursday, August 02, 2012 3:45 PM
Hi,
I think, your binding is set up is incorrect. Change it to
Binding binding = new Binding("CurrentValue");
and discard the line "binding.Source = textData.CurrentValue;".
A second point, where you might have misunderstood something is: the class "TextBoxData" must implement the INotifyPropertyChanged interface and the property setter (of CurrentValue) must raise the PropertyChanged event.
A third point is: By setting the BindingMode to OneWay, you let changes to "CurrentValue" pass to the TextBox, but not vice versa. On the other hand, by setting the UpdateSourceTrigger (to whatever), you specify, which event will lead to an update of "CurrentValue". These two can't go together. So either specify TwoWay as BindingMode (data will be passed in both directions) or discard the UpdateSourceTrigger.
Cheers
Jürgen- Marked As Answer by Ajin Prasad Monday, August 06, 2012 4:42 PM

