Can't bind to View's property - wpf

In my view's xaml fileļ¼Œ I have this line:
TextBox Text="{Binding MyModel.Text}"
Everytime I ran the program, it gave me this error message:
System.Windows.Data Error: 40 : BindingExpression path error:
'MyModel' property not found on 'object' ''MyModel'
(HashCode=56593137)'. BindingExpression:Path=MyModel.Text;
DataItem='MyModel' (HashCode=56593137); target element is 'TextBox'
(Name=''); target property is 'Text' (type 'String')
I'm sure my spelling is right.
I set my view's DataContext to ViewModel. Could that be a problem?

If your DataContext is set to MyModel you should just have to write:
<TextBox Text="{Binding Text}"/>
Adding the extra MyModel is repetitive and results in looking for MyModel.MyModel.Text.

Just TextBox Text="{Binding Text}"

Since you're view is bound to your view-model (good), then your view-model needs to have a property that your view will bind to:
TextBox Text="{Binding MyViewModelsProperty}"
In your situation, you'll need to set your model's property from your view-model (MyViewModelsProperty setter).
Let me know if you need more info.

Related

Binding to dependency property via PlacementTarget fails - wrong path syntax?

No problem
I created a dependency property which takes a string value. I set it on a TextBlock and it works:
<TextBlock dp:ElementDataContext.ElementName="LvMain">
I verified that the property ElementDataContext.ElementName is set to "LvMain".
Problem
Now here is the problem: in the TextBlock's context menu I want to bind to this dependency property via PlacementTarget.
Here is how I try to do it. This is an excerpt of my XAML containing TextBlock and ContextMenu:
<TextBlock dp:ElementDataContext.ElementName="LvMain">
<TextBlock.ContextMenu>
<ContextMenu Tag="{Binding PlacementTarget.(dp:ElementDataContext.ElementName), RelativeSource={RelativeSource Self}}">
This fails at runtime. When opening the context menu it gives me a "BindingExpression path error":
BindingExpression path error: '(dp:ElementDataContext.ElementName)' property not found on 'object' ''TextBlock' (Name='')'. BindingExpression:Path=PlacementTarget.(dp:ElementDataContext.ElementName); DataItem='ContextMenu' (Name='contextMenu'); target element is 'ContextMenu' (Name='contextMenu'); target property is 'Tag' (type 'Object')
I suspect my binding path is wrong. I tried
PlacementTarget.(dp:ElementDataContext.ElementName)
PlacementTarget.dp:ElementDataContext.ElementName
PlacementTarget.ElementDataContext.ElementName
Nothing works. What is the correct syntax? Is this even possible?
The property path syntax PlacementTarget.(dp:ElementDataContext.ElementName) is correct, but you also have to explicitly write the Path=... part in the property expression:
<ContextMenu Tag="{Binding Path=PlacementTarget.(dp:ElementDataContext.ElementName),
RelativeSource={RelativeSource Self}}">
However, the Implicit Path section in Binding Markup Extension does not mention this behaviour.

Accessing a child user control's data context in the parent

In my WPF+MVVM application I have a View which hosts another usercontrol. The child usercontrol does not follow the MVVM way (because I'm simply hosting a Visio activeX object there), so I'm using the code behind class.
In the View I'm using this code:
<uc:VisioControl Grid.Row="2" x:Name="visioControlUC"
VisioFileName="{Binding ElementName=tbFullFileName,Path=Text, UpdateSourceTrigger=PropertyChanged}"/>
In the same View, I have a Label element where I want to display a field value of a DependencyProperty named SelectedNodeCustomProperties defined on the child user control
<Label x:Name="lbNodeIdValue" DataContext="{Binding ElementName=visioControlUC}" Content="{Binding Path=SelectedNodeCustomProperties.Id, UpdateSourceTrigger=PropertyChanged}"/>
However, this is not working. Running in Debug mode I can see this binding exception in the Output window:
BindingExpression path error: 'visioControlUC' property not found on 'object' ''NSDVizualizerViewModel' (HashCode=65573909)'. BindingExpression:Path=visioControlUC.SelectedNodeCustomProperties.NodeId; DataItem='NSDVizualizerViewModel' (HashCode=65573909); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
So, why is it that it's expecting that the child user control be defined in the viewmodel and how can I set the DataContext to the user control when binding the label content?
Thanks,
Adrian
EDIT: To the person who downvoted my question, maybe you can explain why? Is there a similar question on the forum that I haven't found maybe?
Try
<Label x:Name="lbNodeIdValue"
Content="{Binding ElementName=visioControlUC,
Path=SelectedNodeCustomProperties.Id,
UpdateSourceTrigger=PropertyChanged}"/>

Relative binding command with silverlight WP7

I have an error when binding my command to a button in an ItemsControl.
This is my code :
<phone:PhoneApplicationPage.DataContext>
<ViewModel:MyViewModel />
</phone:PhoneApplicationPage.DataContext>
with :
<ItemsControl ItemsSource="{Binding MyList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="Test"
cmd:ButtonBaseExtensions.Command="{Binding MyViewModel.TestCommand}"
cmd:ButtonBaseExtensions.CommandParameter="{Binding}"/>
</ItemsControl.ItemTemplate>
</ItemsControl>
And I get :
System.Windows.Data Error: BindingExpression path error: 'MyViewModel' property not found on '...' '...' (HashCode=77119633). BindingExpression: Path='MyViewModel.ChooseCommand' DataItem='...' (HashCode=77119633); target element is 'System.Windows.Controls.Button' (Name=''); target property is 'Command' (type 'System.Windows.Input.ICommand')..
Of course, I should use an absolute binding or a relative one, but I don't know how to do that.
Thanks in advance for any help
Your Button is within an ItemsControl which is bound to youur MyList property, which I am guessing is a List or some IEnumerable type. The DataContext of each Button will be the item within the MyList that it represents.
You are correct that to bind the buttons to your top-level view model you would need some sort of relative source binding, which Silverlight (3) does not support.
I created a relative source binding replacement for Silverlight here:
http://www.scottlogic.co.uk/blog/colin/2009/02/relativesource-binding-in-silverlight/
However, for WP7, where performance really matters, I would not use it!
Why not simply create the relationship you need in your view model? i.e. for each item in MyList (let's call them MyListItem), expose a property which points back to the parent view Model. In other Words, have a MyListItem.Parent property which points to MyViewModel.

How can I make UIElement support binding?

DependencyProperties on UIElements do not support databinding (you get something like:
"Cannot find governing
FrameworkElement..")
. If you try, you get an error because WPF can not resolve the DataContext. From what I know, you get binding support if you inherit FrameworkElement or Freezable, but In this case I can not simply change the base class. Is there any way to get the UIElement to support data binding?
I've tried to add the DataContext property to the UIElement class like this:
FrameworkElement.DataContextProperty.AddOwner(typeof(Bitmap), new
FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
I also tried to bind by specifying "ElementName" in the binding expression, but I am still unable to resolve the parent DataContext (I thought that binding explicitly by ElementName would simply remove the need to resolve the DataContext).
This is the binding. The class in question is called "Bitmap".
<Utils:Bitmap Source="{Binding Path=Icon}" />
<TextBlock Grid.Row="1" Grid.ColumnSpan="3" MaxWidth="90" Text="{Binding Path=Name}" TextWrapping="Wrap" TextAlignment="Center"/>
The textblock binding works as expected, the first binding does not. The bound viewmodel has both properties (I bound to the Image class before and it worked).
The bitmap class can be found at this blog: http://blogs.msdn.com/b/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx
With some extended binding diagnostics, I get this output:
System.Windows.Data Warning: 65 : BindingExpression (hash=14926099): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Icon; DataItem=null; target element is 'Bitmap' (HashCode=117163); target property is 'Source' (type 'BitmapSource')
System.Windows.Data Warning: 63 : BindingExpression (hash=6195855): Resolving source (last chance)
System.Windows.Data Warning: 65 : BindingExpression (hash=6195855): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Icon; DataItem=null; target element is 'Bitmap' (HashCode=55762700); target property is 'Source' (type 'BitmapSource')
System.Windows.Data Warning: 63 : BindingExpression (hash=48657561): Resolving source (last chance)
System.Windows.Data Warning: 65 : BindingExpression (hash=48657561): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Icon; DataItem=null; target element is 'Bitmap' (HashCode=35264868); target property is 'Source' (type 'BitmapSource')
You have to inherit FrameworkElement to use data binding. If you cannot change the base class, the only option you have is, as H.B. said, create an adapter that will be derived from FrameworkElement and will delegate all the functionality to an instance of the existing class derived from UIElement.
See http://msdn.microsoft.com/en-us/library/ms743618.aspx for more information on what the base framework classes (like UIElement and FrameworkElement) provide.
Update:
Even though MSDN (link above) says that the data binding support is introduced on the FrameworkElement level, it IS possible to set binding on any DependencyObject. The only thing is that in this case you cannot use DataContext as an implicit source for the binding and you cannot use ElementName for referring to the source.
What you can do is to set binding programmatically and specify source explicitly:
BindingOperations.SetBinding(MyBitmap, Bitmap.IconProperty, new Binding() { Source = this.DataContext /* Or any other source */, Path = new PropertyPath("Icon")});
OR you can use a little trick and use RelativeSource for referring to an element in the visual tree (in this case any parent FrameworkElement):
<Utils:Bitmap Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type FrameworkElement}}, Path=DataContext.Icon}" />
You can use {Binding Source={x:Reference elementName}} instead of {Binding ElementName=elementName}.
As noted you can bind on any object which inherits from DependencyObject, if you want a DataContext, I'd suggest you just make the class inherit from FrameworkElement. Even shapes like Rectangle do so, if you have some image-control it only makes sense to choose a higher level as the base-class.

Binding to the Current Item (WPF)

I am attempting to bind a ListView control to a DataTable, but the WPF binding system seems to be complaining about the binding path I specify.
As an example, a GridViewColumn is defined as follows:
<GridViewColumn Header="ColumnTitle"
DisplayMemberBinding="{Binding Path=/,
Converter={StaticResource myConverter}}"/>
As far as I understand (and MSN seems to support me), specifying Path=/ should make the binding on the current item of the data collection.
The error I receive (in the trace window) is:
System.Windows.Data Error: 39 : BindingExpression path error: ''
property not found on 'current item of collection' ''OrdersRow'
(HashCode=680171)'. BindingExpression:Path=/; DataItem='OrdersRow'
(HashCode=680171); target element is 'TextBlock' (Name=''); target
property is 'Text' (type 'String')
This is giving me the impression that / isn't even a valid path, and WPF is expecting something after the slash. If so, how else would I bind to the current item? Why am I getting this error in the first place?
Have you tried omitting the Path parameter?
<GridViewColumn Header="ColumnTitle"
DisplayMemberBinding="{Binding Converter={StaticResource myConverter}}"/>
I think the confusion is that the DataContext for the GridViewColumn is not the top collection, but is already the item that is bound to that column, so you don't need to specify a path.
The time that the you may use a path like this is if your control's DataContext is a List and you want to bind to the selected item. A possible example would be.
<Combobox DataContext={Binding ColourList}
DataSource={Binding} <!--Bind to the datacontext -->
ForeColor={Binding/} <!--Bind to the currently selected item
in the datacontext -->
/>

Resources