I have a mutilingual wpf project. I am using ResourceDictionary to do this. For static TextBlock I can change the Text language by:
<TextBlock Text="{Binding Sample, Source={StaticResource Resources}}" />
BUT how should I change a dynamic TextBlock Text. It seems impossible to do it in this way:
<TextBlock Text="{Binding Sample}
And in the code behind:
Sample = Resources.SampleText;
If this is impossible. Is there any other options? Thanks in advance!
The class where the Sample property is define should implement the INotifyPropertyChanged interface and raise change notifications:
public class Translations : INotifyPropertyChanged
{
private string _sample;
public string Sample
{
get { return _sample; }
set { _sample = value; OnPropertyChanged("Sample"); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Only then you will be able to update the TextBlock dynamically by simply setting the Sample source property to a new string value.
Related
I am new to WPF. I have binded the source class properties to target controls successfully. But whenever the properties value changes the UI controls not reflecting the updated data. Please help
WPF Code:
<Label Name="Panel_ch1Mode" Content="{Binding Path=Mode, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" FontFamily="Roboto Regular" FontSize="16" Foreground="#FFFFFF"/>
My Class:
public class ClassName: INotifyPropertyChanged
{
//Auto Refresh
private string mode;
public string Mode
{
get
{
return this.mode;
}
set
{
this.mode = value;
NotifyPropertyChanged("Mode");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Try this: Just remove from xaml the UpdateSourceTrigger=PropertyChanged, Mode=TwoWay. )
Improve your implementation of INotifyPropertyChanged linke this:
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
In code behind please check if the ViewModel is "wired" to the View:
public YourView()
{
InitializeComponent();
DataContext = new ClassName();
}
You have to keep in mind that a binding is always related to DataContext.
I have a TextBlock control inside a HubSection in a Windows 8.1 Universal app.
<TextBlock x:Name="api_enabled_label"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Text="{Binding APIinfotext}" />
Now when the page is launched, in the contrustor, there is a method that is run.
public string APIinfotext { get; set; }
public sealed partial class MainPage : Page {
VoipMS voip_service = new VoipMS("shoukatali#hotmail.com", "Kitt0cat");
public string APIinfotext { get; set; }
public MainPage() {
this.InitializeComponent();
// disable sections until API is enabled
mainpagehub.Sections[1].IsEnabled = false;
mainpagehub.Sections[2].IsEnabled = false;
//check for API and enable sections
checkAPI();
}
private async void checkAPI() {
//irrelevant code above
switch (result) {
case "success":
APIinfotext = "Your API is connected";
break;
//irrelevant code below
}
}
So why dosnt this work? I set the DataContext of the Textblock to the current class (which is the MainPage partial class) and the property is a public property.
Note: Today is my first time working with .net 4.5 with XAML after a huge break at the .net 2.0 framework with WinForms.
Your binding doesn't know that APIinfotext property has changed. To let the bindings know that the property has changed you can do one of the following. The first one is the easiest.
1) implement INotifyPropertyChanged interface and raise the PropertyChanged changed event once APIinfotext has changed (PropertyChanged("APIinfotext"));
2) Have an event called APIinfotextChanged with the standard event signature and raise that event after the property has changed.
3) Implement your property as a DependencyProperty (not an ideal solution in this case).
You might be missing the part where you have to RaiseProperyChange NotifyPropertyChage to update the bindings. your Model should implement the INotifyPropertyChanged interface
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
then
RaisePropertyChanged("APIinfotext");
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.propertychanged.aspx
Looks like you need a very simple example of what the other two are talking about. Let's assume nothing. You need to set the DataContext correctly, plus raise the event. This is as simple as I can put it, when you click on the button it will change the TextBox because I change the Property which raises the event.
XAML
<Page>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<TextBox Text="{Binding APIinfotext}" Height="100" Width="400" HorizontalAlignment="Left"/>
<Button x:Name="myButton" Content="Change Text" Height="200" Width="400" Click="myButton_Click"/>
</StackPanel>
</Grid>
</Page>
C# (Pay attention, to the SET part of the APIinfotext)
using System.ComponentModel; // INotifyPropertyChanged
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private string _apiinfotext = "Default Text";
public string APIinfotext
{
get { return _apiinfotext; }
set
{
_apiinfotext = value;
RaisePropertyChanged("APIinfotext");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
this.APIinfotext = "Don't confuse movement for progress.";
}
}
I have a wpf gui page with a textbox that is bound to a property of an innerclass in my window. I have defined the textbox to be bound like so:
XAML:
<TextBox Name="shhh" Text="{Binding Path=derpDerp, Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}" />
CodeBehind:
namespace ...
{
public partial class MainWindow : Window
{
innerclass definition....
public Herp derp;
public MainWindow()
{
...
derp = new Herp();
shhh.DataContext = derp;
...
}
{code that changes derp.derpDerp}
}
}
InnerClass:
public class Herp : INotifyPropertyChanged
{
private secret = "";
public event PropertyChangedEventHandler PropertyChanged;
public Herp(string derp)
{
secret = derp;
}
public string derpDerp
{
get{ return secret; }
set{ secret = value; onPropertyChanged("derpDerp"); }
}
private void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
What I was wondering is if I can declare the source of the textbox in the xaml. I have seen many examples that say to set the textbox to the datacontext of the parent like the window or a container around the textbox. However i don't find that very intuitive if only 1 control needs the data. It would make sense if I have several textboxes and a stackpanel with a datacontext.
In my implementation I create the object in code and set the datacontext to just the textbox. Is there an equivalent xaml solution?
Something like:
<TextBox Source="something" Path=derpDerp..../>
without setting a datacontext to a container or the window. Also, I didn't know how to set the datacontext of the window to my property correctly because it's an inner class with a namespace of the namespace.the window class or something like that.
What would be the proper way of just giving the textbox a datasource or if not possible how do I reference the innerclass and set the source to the window?
Yes, you can create an instance of a class and set it as DataContext on any control in XAML. The general solution would be like this:
<Window x:Class="MyProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyProject">
<Window.Resources>
<local:Herp DerpDerp="This is Derp!!" x:Key="derp"/>
</Window.Resources>
<Grid>
<TextBox Text="{Binding Source={StaticResource derp}, Path=DerpDerp}"/>
</Grid>
Notice that I defined a new xmlns object called local, which points to the namespace in which the class I'm trying to create resides (in this case, it's Herp).Then, in my Window.Resources, I create an instance of Herp, and set a value for the DerpDerp property. Also notice that I gave the class a key, which is necessary in order for the TextBox to find it and bind to it.
Big note: In order for you to be able to create an instace of a class in XAML, the class needs to have a parameter-less constructor! So I changed Herp a little bit:
namespace MyProject
{
public class Herp : INotifyPropertyChanged
{
private string m_derp;
public Herp()
{
}
public string DerpDerp
{
get { return m_derp; }
set { m_derp = value; OnPropertyChanged("DerpDerp"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
Finally, in your TextBox, you use the Source element in your binding to bind to the object:
<TextBox Text="{Binding Source={StaticResource derp}, Path=DerpDerp}"/>
I'm new to programming in Windows Phone 8. I am studying "The Binding". I try to bind the property "Value" of a Slider, but when running the application I do not see any change.
The XAML code is this:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<Slider Minimum="1" Maximum="100" Value="{Binding Valor}" />
</StackPanel>
</Grid>
The ViewModelBase class is this:
public class VMBase : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public VMBase() {}
public void RaisePropertyChanged(string PropertyName) {
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
The ViewModel class is this:
public class VMSlider : VMBase {
private int _valor;
public VMSlider() {
_valor = 43;
}
public int Valor {
get { return _valor; }
set {
_valor = value;
RaisePropertyChanged("Valor");
}
}
}
In the code-behind class of my XAML y write this:
this.DataContext = new ViewModel.VMSlider();
I need to say why.
Thank you.
The Value property on the Slider control is of type Double. Your Binding doesn't work because Valor is a value of the wrong type.
You must either implement a Value Converter or change Valor to a Double.
Is it usable or this doesn't work: to change the Text Box.Text and the property behind to change can a binding of this type be made(i know that this can be made with an event from Text Box, i am looking for some kind of binding that can be made) ?
Should i just use Text Box.Text in my cod?
<TextBox Text="{Binding Path=NumeClient, Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="117,21,0,0" Name="textBox1" VerticalAlignment="Top" Width="249" />
public string NumeClient { get; set; }
If I understand the question correctly, you're asking how to setup a two way binding to the Text property of a TextBox?
<TextBox Text="{Binding Path=YourProperty, Mode=TwoWay}" />
This Makes both your property changes the TextBox and the TextBox changes the property (from MSDN)
Add in your class contructor DataContext = this;
public class Person : INotifyPropertyChanged
{
private string name;
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
public string PersonName
{
get { return name; }
set
{
name = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("PersonName");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
XAML :
<TextBox Text="{Binding Path=PersonName, Mode=TwoWay}" />
Hope it helps