Super simple binding example - c#

I'm trying to do a simple binding but I'm having some problems. I have a text block and a button. The textblock is binded to a property called "word". When you press the button the value of word changes and I want to automacally update the text block. This is a classic example, please explain me what I'm doing wrong:
namespace WpfApplication5
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string _word;
public string word
{
get { return _word; }
set
{
_word= value;
RaisePropertyChanged(word);
}
}
private void change_Click(object sender, RoutedEventArgs e)
{
word= "I've changed!";
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
And my XAML with the binding:
<Window x:Class="WpfApplication5.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">
<Grid>
<TextBlock HorizontalAlignment="Left" Margin="210,152,0,0" TextWrapping="Wrap" Text="{Binding word}" VerticalAlignment="Top"/>
<Button x:Name="change" Content="Change" HorizontalAlignment="Left" Margin="189,235,0,0" VerticalAlignment="Top" Width="75" Click="change_Click"/>
</Grid>
</Window>

You are raising a PropertyChanged event for a property named I've changed!, because you pass the value of the property word to RaisePropertyChanged. You need to pass the name of the property instead:
RaisePropertyChanged("word");
This answer assumes that the data context is set correctly. If not, you need to fix that too:
DataContext = this;

Related

INotifyPropertyChanged does not work when the property set to another value with mode = twoway

My Xaml
<TextBox Text="{Binding MyVal, Mode=TwoWay}" ></TextBox>
My Viewmodel
private string myVar;
public string MyVal
{
get
{
return myVar;
}
set
{
if (value.Length > 6)
myVar = value;
else
myVar = "Not a valid INPUT";
OnPropertyChanged("MyVal");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
when ever user enters a less than 6 char string the textbox should disply error message. instead of that the textbox text is remains same as the user input. But the variable value is changing as expected.
I'm using WinRT app please help Thanks In advance.
I would change your xaml code this way :
<TextBox Text="{Binding MyVal, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ></TextBox>
Now every time your property will change, the view will be notified.
and if the UI is still not updated try adding IsAsync=true :
<TextBox Text="{Binding MyVal, Mode=TwoWay, IsAsync=true}"></TextBox>
Your example easily works when I use it in WPF app.
Rembember that the trigger fires when focus is lost on the control.
I've added second textbox, so when you change focus on it, the first TextBox with binding will fire the event.
View
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
this.DataContext = new ViewModel();
InitializeComponent();
}
}
}
View (XAML)
<Window x:Class="WpfApplication1.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">
<Grid>
<TextBox HorizontalAlignment="Left" Height="23" Margin="223,173,0,0" TextWrapping="Wrap" Text="{Binding MyVal, Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="281,252,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
</Grid>
</Window>
ViewModel
namespace WpfApplication1
{
class ViewModel : INotifyPropertyChanged
{
private string myVar;
public string MyVal
{
get
{
return myVar;
}
set
{
if (value.Length > 6)
myVar = value;
else
myVar = "Not a valid INPUT";
NotifyPropertyChanged("MyVal");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public ViewModel() { }
}
}
The problem is that you are changing the value in the setter, and then firing the INPC event directly. However, since the value is being currently changed anyway, the TextBox ignores the event. See also this question.
This exact implementation of this was changed several times in .NET 3.5/4.0/4.5, so it currently (4.5) works as you expect (but has other side effects, ex. when binding to a double).
The easiest solution for you would be firing the INPC event with a slight delay, which means the TextBox is forced to read the (possibly updated) value again:
Dispatcher.CurrentDispatcher.BeginInvoke(NotifyPropertyChanged("MyVal"));

Databinding not working for user control - PropertyChanged always null

I have a problem with data binding. A test application that I have looks as follows:
There's a mainwindow:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:WpfApplication2"
x:Name="main"
Title="MainWindow" >
<StackPanel >
<Button Content="Button" Click="Button_Click"/>
<Controls:UserControl1 />
</StackPanel>
</Window>
And a user control:
<UserControl x:Class="WpfApplication2.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
x:Name="uc"
>
<Grid >
<TextBox Width="40" Text="{Binding ElementName=main,
Path=Status, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</UserControl>
I want to click the button on the main window to have the value of text box in user control updated:
The code of MainWindow file:
namespace WpfApplication2
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private string _status;
public string Status
{
get { return _status; }
set
{
if (value != _status)
{
_status = value;
RaisePropertyChanged("Status");
}
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (Status == "one")
Status = "two";
else
Status = "one";
}
}
}
And the code of UserControl:
namespace WpfApplication2
{
public partial class UserControl1 : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, e: new PropertyChangedEventArgs(propertyName));
}
public UserControl1()
{
InitializeComponent();
}
}
}
I don't understand why doesn't it work, but the PropertyChanged is always null. The example is in the simplest form I can imagine...
You are trying to access the parent window using the ElementName binding, as far as I am aware, that is not possible. You can however use a relative source binding to get the parent window:
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=Status}" ... />
Follow up edit:
Your child user control should look like this:
<UserControl
...
x:Name="usr">
<Grid>
<TextBlock Text="{Binding Message, ElementName=usr}"/>
</Grid>
</UserControl>
You will then need to create a dependency property called 'Message' (This is just an example, I'm not sure what you want to call this property).
public partial class YourUserControl: UserControl
{
public string Message
{
get { return (string)GetValue(MessageProperty); }
set { SetValue(MessageProperty, value); }
}
// Using a DependencyProperty as the backing store for Message. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MessageProperty =
DependencyProperty.Register("Message", typeof(string), typeof(YourUserControl), new PropertyMetadata(""));
public UserControl1()
{
InitializeComponent();
}
}
Then, when you declare this in your parent user control, simply set the binding of the Message property to whatever property you need to bind to in your parent user control:
<YourNamespace:YourUserControl Message="{Binding PropertyName, ElementName=elementName}" />

Windows store app - two elements one object binding

What is the best way to acchieve this, what I am going to describe bellow.
I have two textboxes with twoway bindings on the same object and same property.
Now, when I update text in one textbox I wish other textbox to grab the same value again from object. Is that even possible, or I have to do this manually. For an example, I can use TextChanged event and set this value.
Yes you can bind a single property to two controls
If this class is your DataContext (viewmodel)
public class Bind : INotifyPropertyChanged
{
private string _text1;
public string text1
{
get
{
return _text1;
}
set
{
_text1=value;
NotifyPropertyChanged("text1");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
In XAML
<UserControl x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525"
xmlns:ViewModel="clr-namespace:WpfApplication1">
<UserControl.DataContext>
<ViewModel:Class1/>
</UserControl.DataContext>
<Grid>
<TextBox Width="150" Height="50" Text="{Binding text1, Mode=TwoWay}"/>
<TextBox Text="{Binding text1, Mode=TwoWay}" Margin="0,232,0,0"/>
</Grid>
</UserControl>

Binding in TextBlock doesn't work in WPF

I want to dynamically change TextBlock text in my Class.
XAML-Code:
<TextBlock Name="Footer_text" Text=""/>
C#:
string footerMainMenuText = "Setting";
Binding set = new Binding("");
set.Mode = BindingMode.OneWay;
set.Source = footerMainMenuText;
Footer_text.DataContext = footerMainMenuText;
Footer_text.SetBinding(TextBlock.TextProperty, set);
I checked last line, and the Footer_text.Text is set correctly. ( Footer_text.Text="Setting"), but TextBlock in my application doesnt show "Setting". What is the problem here?
If you are binding - why not just do it in XAML instead? Looking at your code it's kind of pointless - you might as well just go
Footer_text.Text = "Setting";
You should ideally do it in XAML or at least provide something for it to bind to
<TextBlock Text="{Binding SomeProperty}" />
I'm not sure why you would bind a 'string' on it's own to anything...do you have an object which you need to bind to the text property?
Also using
Binding("")
What does that do? A blank path? Not sure what the binding target would be there... have you tried
Binding()
instead?
Edit:
Also the reason why your binding is not updating the control, is probably because you haven't bound to an object which implements INotifyPropertyChanged or a similar interface. The controls need to know when values have changed, so I'd imagine that binding to 'string' isn't giving the TextBlock the proper notification when it changes
Edit 2:
Here is a quick example of binding working:
My window class Window.cs:
<Window x:Class="WpfApplication1.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">
<Grid>
<StackPanel>
<TextBlock x:Name="txtName" Text="{Binding Name}"></TextBlock>
<Button Click="Button_Click">Click me 1</Button>
<Button Click="Button_Click_1">Click me 2</Button>
</StackPanel>
</Grid>
</Window>
The code behind in Window.xaml.cs
public partial class MainWindow : Window
{
SomeObjectClass obj = new SomeObjectClass();
public MainWindow()
{
InitializeComponent();
txtName.DataContext = obj;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
obj.Name = "Hello World";
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
obj.Name = "Goobye World";
}
}
The object to bind to (with INotifyPropertyChanged)
class SomeObjectClass : INotifyPropertyChanged
{
private string _name = "hello";
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
Clicking the buttons changes SomeObject.Name, but it updates the textbox.

Data Binding problem

I want to do something like this diagram Data Binding Diagram.
If i update TextBox text Then update TextBlock text and Property and if i change Property Value then also update Textbox and textBlock text. Please tell me how can i do it using WPF ????
Thank`s For Help.
Im not sure if I understand right your question. Are the two Textboxes in the same view or in different?
Here a solution with 2 textboxes in the same view:
View (xaml):
<Window x:Class="Sandbox.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"
Name="mainWindow">
<StackPanel>
<TextBox Name="UpperTextBox" Text="{Binding ElementName=LowerTextBox, Path=Text,UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Name="LowerTextBox" Text="{Binding MyValue, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
View-Codebehind (xaml.cs):
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MyViewModel();
}
}
ViewModel:
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string _myValue;
public string MyValue
{
get { return _myValue; }
set
{
_myValue = value;
OnPropertyChanged("MyValue");
}
}
}

Categories

Resources