I am trying to get the get the sum to update in the textblock, however I'm only able to get it updated through restarting the windows phone emulator. Why is it so?
Code in DisplayBill.xaml
<TextBlock x:Name="lbTotalAmt" Text="{Binding Path=Sum, Mode=TwoWay, UpdateSourceTrigger=Explicit}" Margin="0,364,0,10" Grid.Row="1" />
Code in ViewModel.cs
private string _Sum;
public string Sum
{
get {return _Sum;}
set
{
_Sum = value;
NotifyPropertyChanged("Sum");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
// Used to notify Silverlight that a property has changed.
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
if (propertyName == "ToDoBills")
UpdateSumValue();
}
private void UpdateSumValue()
{
Sum = ToDoBills.Sum(i => i.Amount).ToString();
}
#endregion
Update
What I'm trying to do is to update the textblock everytime the listbox adds an item. so everytime a new item is added into the listbox, the textblock which display the total amount will update. So my question is how do I go about updating my textblock everytime a new item is added into the listbox? Can anyone help me please? I tried using the binding expression below but to no avail
public DetailPageBill()
{
InitializeComponent();
// Set the page DataContext property to the ViewModel.
this.DataContext = App.todoViewModel;
BindingExpression be = lbTotalAmt.GetBindingExpression(TextBlock.TextProperty);
be.UpdateSource();
}
Try setting UpdateSourceTrigger to PropertyChanged for your TextBlock's binding:
<TextBlock x:Name="lbTotalAmt" Text="{Binding Path=Sum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="0,364,0,10" Grid.Row="1" />
With Explicit no automatic update is performed. MSDN says:
Updates the binding source only when you call the
UpdateSource method.
See MSDN on UpdateSourceTrigger for more information.
Related
In my app I have a user control with the following XAML segment
<StackPanel x:Name="stackPanel" Style="{StaticResource sPanel1}" >
<ToggleButton Style="{StaticResource tButton}">
<TextBlock Text="{Binding Note, Mode=TwoWay}" Style="{StaticResource textBlockStyle}"/>
</ToggleButton>
</StackPanel>
that 'Note' bound in the TextBlock is defined in my model as so:
private string m_Note;
public string Note
{
get { return m_Note; }
set
{
m_Note = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("m_Note"));
}
}
The 'Note' property updates when an event handler from my user control code-behind fires the event:
public void cBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
cm.Note = cBox.SelectedItem.ToString();
}
But every time I select an item from the ComboBox the UI does not update. I know that the binding is correct because when I initialize 'Note' in the model's constructor it does show it's value in the UI, and I know that 'Note' gets the cBox.SelectedItem value because I've walked through the code. What am I missing?
The binding path and mode in the View is correct. That is why you get the value on initialize. Your bound property however is not raising the correct Property Name on property changed. The UI is listening for Note but you are raising m_Note.
You need to update to
private string m_Note;
public string Note
{
get { return m_Note; }
set
{
m_Note = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Note"));
}
}
So I have two global properties Username and CurrentView defined in App.xaml.cs and im binding them in my Views.
App.xaml.cs
public partial class App : Application, INotifyPropertyChanged
{
public static object username;
public object Username { get { return username; } set { username = value; } }
public static Object currentView = new LoginView();
public object CurrentView
{
get { return currentView; }
set { currentView = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
And im binding both of them in different Views.
MainView.xaml
<Page Content="{Binding CurrentView, Source={x:Static Application.Current}}">
</Page>
LoginView.xaml
<TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="165" Margin="218,159,0,0" Text="{Binding Path=Username, Source={x:Static Application.Current}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" />
The binding in MainView is working perfectly fine. It is showing me LoginView which I have initialized CurrentView to in app.xaml.cs and it changes when the source is changed.
However username is not updating which is binded with the textbox in LoginView.
Cant seem to figure out the problem. It should update as Iv set the UpdateSourceTrigger to PropertyChanged.
Any help will be much appreciated :)
The Text property of the TextBox is of type string but your Username property is an object
Consider changing the Username property to string rather than object. If you need it to be an object, you need to have a converter in order for the binding to properly set it.
Also, looking at your binding I notice you have it set up as OneWay. Change that to TwoWay to ensure the Binding updates both ways from Source and Target.
I've searched here a number of times and found a bunch of examples, but can't seem to get anything to work.
I've got a solution set up where a ViewModel refers to a MainViewModel class through a locator. The main view model class has:
public NotifyLog Log
{
get { return LogMgr.Instance.Log; }
}
In it. This allows me to specify:
<TextBox IsEnabled="True" Text="{Binding Log.Text, Mode=OneWay}" />
The NotifyLog is defined as:
public class NotifyLog : INotifyPropertyChanged
{
public NotifyLog()
{
_Log = new StringBuilder();
}
private void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
private StringBuilder _Log;
public void Append(String Value)
{
_Log.Append(Value);
OnPropertyChanged("Text");
}
public string Text
{
get { return _Log.ToString(); }
}
public override string ToString()
{
return this.Text;
}
}
For the initial start of the application, the text box is populated but, the OnPropertyChanged handler is never automatically populated by the binding so no changes are detected. I'm doing something wrong, I just don't know what...
Thanks for your time,
BlD
if you want to update the log when typing in the text box you need to change the binding mode to TwoWay. also the event is triggered when you exit from the text box, not on each char typed.
if you want to update the text box when the log is changed you need to add a setter to the Text property and raise the NotifyPropertyChanged event (in the setter).
also check the output of the program for some binding errors.
To the line:
<TextBox IsEnabled="True" Text="{Binding Log.Text, Mode=OneWay}" />
Try adding the "UpdatedSourceTrigger" like so:
<TextBox IsEnabled="True" Text="{Binding Log.Text, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
My event below (OnSourceUpdated) is not getting handled.
XAML:
<StackPanel x:Name="MyStackPanel"
Orientation="Horizontal"
DockPanel.Dock="Top">
<TextBox Text="{Binding Side, Mode=TwoWay}"
Width="100"/>
<TextBlock Background="Yellow"
Text="{Binding Side, Mode=OneWay,
NotifyOnSourceUpdated=True}"
Width="100"
SourceUpdated="OnSourceUpdated"
Binding.SourceUpdated="OnSourceUpdated"/>
</StackPanel>
C#:
....
MyStackPanel.DataContext = new MyItemClass() { Side = "Test" };
....
private void OnSourceUpdated(Object sender, DataTransferEventArgs args)
{
var i = args.Property;
}
public class MyItemClass : INotifyPropertyChanged
{
private string _side;
public string Side
{
get { return _side; }
set
{
_side = value;
OnPropertyChanged("Side");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
I have all the relevant settings done like NotifyOnSourceUpdated & SourceUpdated & Binding.SourceUpdated etc.
From msdn: Binding.SourceUpdated attached event occurs when a value is transferred from the binding target to the binding source, but only for bindings with the NotifyOnSourceUpdated value set to true
In the Binding of TextBlock, there is no value transfer from the binding target (TextBlock.Text) to the binding source (Side). Thus SourceUpdated cannot be fired.
Instead SourceUpdated can be fired on the first binding. Indeed here the target binding TextBox.Text can change the binding source (Side).
Maybe I'm missing something, but I'm thinking your approach to updating is a bit strange. Is there a reason you're not just going with
<TextBlock Text="{Binding foo, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" ... />
If you're just interested in updates coming from source, that's normally the way of doing it. Calling
OnPropertyChanged( "PropertyName" )
covers the rest.
I want to read value entered in the NumericUpDown control. How do i read it?
XAML Layout is follows
<StackPanel Style="{StaticResource StackPanelStyle_LableValue}">
<TextBlock Style="{StaticResource TextBlockStyle}"
Text="{Binding Path=ViewItem.Addition, Source={StaticResource LocalizedStrings }}" />
<inputToolkit:NumericUpDown Style="{StaticResource NumericUpdownStyle_Addition}"
Value="{Binding Items.RightSpecGlass.Addition, Mode=TwoWay}"
TabIndex="8" />
</StackPanel>
You can use
numericUpDown.Value; // To get decimal value of control
or
numericUpDown.Text; // To get value as string of control
Well, Since you have bind your view context, I think there is no reason to avoid get NumericUpDown's value except :
1- Maybe you forgot to initialize those classes or properties Items and/or RightSpecGlass
2- Your class doesn't implement INotifyPropertyChanged to raise when any control's value change in view. Addition property has to raise property change event in its setter.
public event PropertyChangedEventHandler PropertyChanged;
public virtual void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
private int _addition;
public Int32 Addition
{
get { return _addition; }
set
{
_addition= value;
RaisePropertyChanged("Addition");
}
}
hope this help.