How to bind a textblock's text through XAML using a property? - silverlight

I am working on a Silverlight application, and I want to bind the simple text property of textblock through a property of string type.
What I did was:
<TextBlock Text="{Binding Name}"/>
Code behind:
public string Name{get;set;}
Name = "Testing..!";
but it will not work.

To expand on anatoliiG's answer (which will work): Data binding refers to properties on the DataContext property of the current element by default. This means that your
<TextBlock Text="{Binding Name}" />
is actually translated to
Set the value of the Text property to this.DataContext.Name
(DataContext is inherited, so if it is not explicitly set on the TextBlock it will check the parent, then the parent of the parent etc etc)
You can resolve your problem in one of two ways:
You can set the value of this.DataContext on the parent to the parent itself (as anatoliiG suggests). This means that when it looks up this.DataContext.Name it will be checking the Page itself, which is where your Name property is found.
You can change your Binding so it looks at the Page instead of Page.DataContext when it is looking up bindings. You can achieve this using the RelativeSource markup extension:
This translates to:
Find the first ancestor of the TextBlock that is of type Page, and bind to the Name property on that object
As a final note, you will also need to implement INotifyPropertyChanged on your DataContext object if you are going to ever change the value of Name.
Oh, and you should be using view models as the DataContext instead of the Page itself!

Answer to your question is: in Page_Loaded event set LayoutRoot.DataContext = this;. But it is more hack, than good practice.
You should take a look into MVVM pattern and INotifyPropertyChanged and create ViewModel which will contain this property.

Related

Checkbox binding not working

I searched the forum and did everything as advised to create dependancy property and bind it to checkbox, but for some reason it doesn't bind.
<CheckBox IsChecked="{Binding ElementName=MainWindow, Path=isLoop}" Content="" Height="22" HorizontalAlignment="Left" Margin="250,208,0,0" x:Name="checkBox1" VerticalAlignment="Top" Width="22" />
C#
public bool isLoop
{
get { return (bool)GetValue(isLoopProperty); }
set { SetValue(isLoopProperty, value); }
}
public static readonly DependencyProperty isLoopProperty =
DependencyProperty.Register("isLoop", typeof(bool), typeof(MainWindow), new UIPropertyMetadata(true));
You've made some key mistakes in your sample.
First, you are not binding to an object that supports your "isLoop" property (unless "MainWindow" is a custom control that has that property). Somewhere in that CheckBox's hierarchy, you need to set the DataContext to an object that supports it, or bind to an element that has that property.
Second, you should rarely, if ever, create a dependency property in your business object. For business objects, follow the INotifyPropertyChanged pattern. Typically, you should create dependency properties in visual UI elements, such as custom controls in order to be able to bind data to them (a target, not the source).
So, to fix your problem, you should probably create an object that implements INotifyPropertyChanged, create an IsLoop property that throws the NotifyPropertyChanged event in the setter, and set this object as the DataContext to the CheckBox's parent container (or further up the hierarchy if appropriate).
HTH
You are binding to the Window itself. Do you mean to do that? Unless your code example is in the code behind then the binding will not work.
Since you're using an ElementName binding, I am guessing you are binding to a UI element. The problem is, none of the default UI elements come with a property called isLoop, so your binding is invalid.
There are a few things you can try.
If your isLoop property is part of the object named MainWindow's DataContext, change your binding to DataContext.isLoop
<CheckBox IsChecked="{Binding ElementName=MainWindow, Path=DataContext.isLoop}" ... />
If isLoop is actually a property on a custom class called MainWindow, such as your dependency property implies, verify that the object named MainWindow is actually of type MainWindow
<local:MainWindow x:Name="MainWindow" />
And if neither of those work, post your full XAML (particularly the part named MainWindow), the code for the class MainWindow, and the code that ties the MainWindow class object with the XAML UI.
The isLoop won't trigger when the checkbox is clicked. That is simply for accessing the depency property in code. You should add a PropertyCallback function and register that in the metadata.

get context in converter?

I have a usercontrol whose the context is a given object Foo.
I have a textbox in readonly mode, whose the text changes according to a selected value in a combobox (which is bind two-way). The value of the textbox uses the values of a lot of fields in Foo.
For now, I have written a converter Text="{Binding ComboboxValue, Converter={StaticResource MyTextConverter}}, and code-behind, according to the ComboboxValue, I need to return a string composed of other values of Foo. The problem is I can't access the DataContext in the converter, and I can't pass it.
If I bind the context without Path (using Text="{Binding Converter={StaticResource ConnectionStringTextConverter}}), it won't trigger every time my value in the combobox changes (normal).
So, is it possible to it that way ? Or I'm forced to use the Selected event of the combobox ?
Thanks
PS: Actually, what I need is to bind the Text property of the textbox on my DataContext (no Path), but I need the binding to be evaluate each time a property change of the object change. Is this possible ?
You could use the DataContextProxy utility class like this:
Text={Binding ComboBoxValue, Converter={StaticResource MyTextConverter}, ConverterParameter={StaticResource DataContextProxy}}
and then in your converter grab the converter parameter and cast it to a DataContextProxy and use its DataSource property.

Where is the datacontext for the CustomerViewModel in the official MSDN MVVM article?

I speak about josh smith article.
can anyone show me please how the CustomerView.xaml specifically this:j
<TextBox
x:Name="firstNameTxt"
Grid.Row="2" Grid.Column="2"
Text="{Binding Path=FirstName, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
Validation.ErrorTemplate="{x:Null}"
/>
Why is there a Binding to FirstName which is public property in the CustomerViewModel.
There is a datacontext set for the MainViewModel, but not for the CustomerViewModel, so why does the binding work ???
Check out the ResourceDictionary in MainWindowResources.xaml. Josh uses the following code to describe what View should be used if an instance of CustomerViewModel is shown in the main window:
<DataTemplate DataType="{x:Type vm:CustomerViewModel}">
<vw:CustomerView />
</DataTemplate>
We've described that when our DataType is of Type CustomerViewModel, we'll create a new instance of the CustomerView. WPF takes care of the DataContext and creation when it sees the CustomerViewModel type.
From the rest of the article:
Applying a View to a ViewModel
MainWindowViewModel indirectly adds
and removes Workspace ViewModel
objects to and from the main window's
Tab Control. By relying on data
binding, the Content property of a
TabItem receives a
ViewModelBase-derived object to
display. ViewModelBase is not a UI
element, so it has no inherent support
for rendering itself. By default, in
WPF a non-visual object is rendered by
displaying the results of a call to
its ToString method in a TextBlock.
That clearly is not what you need,
unless your users have a burning
desire to see the type name of our
ViewModel classes! You can easily tell
WPF how to render a ViewModel object
by using typed DataTemplates. A typed
DataTemplate does not have an x:Key
value assigned to it, but it does have
its DataType property set to an
instance of the Type class. If WPF
tries to render one of your ViewModel
objects, it will check to see if the
resource system has a typed
DataTemplate in scope whose DataType
is the same as (or a base class of)
the type of your ViewModel object. If
it finds one, it uses that template to
render the ViewModel object referenced
by the tab item's Content property.
The MainWindowResources.xaml file has
a Resource Dictionary. That dictionary
is added to the main window's resource
hierarchy, which means that the
resources it contains are in the
window's resource scope. When a tab
item's content is set to a ViewModel
object, a typed DataTemplate from this
dictionary supplies a view (that is, a
user control) to render it, as shown
in Figure 10.
The DataContext for the MainViewModel in App.xaml.cs serves as a starting point for our application.

WPF Update Binding when Bound directly to DataContext w/ Converter

Normally when you want a databound control to 'update,' you use the "PropertyChanged" event to signal to the interface that the data has changed behind the scenes.
For instance, you could have a textblock that is bound to the datacontext with a property "DisplayText"
<TextBlock Text="{Binding Path=DisplayText}"/>
From here, if the DataContext raises the PropertyChanged event with PropertyName "DisplayText," then this textblock's text should update (assuming you didn't change the Mode of the binding).
However, I have a more complicated binding that uses many properties off of the datacontext to determine the final look and feel of the control. To accomplish this, I bind directly to the datacontext and use a converter. In this case I am working with an image source.
<Image Source="{Binding Converter={StaticResource ImageConverter}}"/>
As you can see, I use a {Binding} with no path to bind directly to the datacontext, and I use an ImageConverter to select the image I'm looking for. But now I have no way (that I know of) to tell that binding to update. I tried raising the propertychanged event with "." as the propertyname, which did not work.
Is this possible? Do I have to wrap up the converting logic into a property that the binding can attach to, or is there a way to tell the binding to refresh (without explicitly refreshing the binding)?
Any help would be greatly appreciated.
Thanks!
-Adam
The workaround here was to add a property to my object (to be used as the datacontext) called "Self" , which simply returned
public Object Self { get { return this; }}
Then in the binding I used this property:
<Image Source="{Binding Path=Self, Converter={StaticResource ImageConverter}}"/>
Then when I call
PropertyChanged(this, new PropertyChangedEventArgs("Self"))
it works like a charm.
Thanks all.
I don't believe there is a way of accomplishing exactly what you need with your current converter. As you mentioned, you could do the calculation in your ViewModel, or you could change your converter into an IMulitValueConverter.
From your specific scenario (the converter tied to a ViewModel class, and a few of its properties), I would lean towards implementing the logic in the ViewModel.
Hmm, you don't show the full implementation. But I think it should update, if the value bound to the GUI provides the PropertyChanged-Event.
Regards

How to do simple Binding in Silverlight?

I understand that Silverlight 3.0 has binding but just want a simple example on how to use this to read a property from a class.
I have a class called Appointment which as a String property called Location:
Public Property Location() As String
Get
Return _Location
End Get
Set(ByVal Value As String)
_Location = Value
End Set
End Property
With a Private Declaration for the _Location as String of course.
I want a XAML element to bind to this property to display this in a TextElement, but it must be in XAML and not code, for example I want something like this:
<TextBlock Text="{Binding Appointment.Location}"/>
What do I need to do to get this to work?
It has to be a Silverlight 3.0 solution as some WPF features are not present such as DynamicResource which is what I'm used to using.
Just to add that my XAML is being loaded in from a seperate XAML File, this may be a factor in why the binding examples don't seem to work, as there are different XAML files the same Appointment.Location data needs to be applied.
You have two options.
If the "Appointment" class can be used as the DataContext for the control or Window, you can do:
<TextBlock Text="{Binding Location}" />
If, however, "Appointment" is a property of your current DataContext, you need a more complex path for the binding:
<TextBlock Text="{Binding Path=Appointment.Location}" />
Full details are documented in MSDN under the Binding Declarations page. If neither of these are working, make sure you have the DataContext set correctly.
You need something in code, unless you want to declare an instance of Appointment in a resource and bind to that but I doubt thats what you want.
You need to bind the Text property to the Property Path "Location" then assign the DataContext of the containing XAML to an instance of the Appointment:-
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding Location}" />
</Grid>
Then in the control's load event:-
void Page_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new Appointment() { Location = "SomePlace" };
}
Note in this case I'm using the default Page control.
If I'm reading correctly, you need to create an instance of Appointment, set the DataContext of the control to that instance and modify your binding to just say: Text="{Binding Location}"
Also, consider implementing INotifyPropertyChanged on your Appointment class to allow the data classes to notify the UI of property value changes.

Resources