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

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}"/>

Related

DataBinding on Custom Control Not Working

I'm sure I am doing something wrong.
Some context: WPF application, MVVM, Entity Framework, etc.
In my ViewModel for a window, I have two properties: MemberCount and EventCount. Both are int.
In my view, I have a 5 instances of a custom control. This custom control has three dependency Properties: ImageData, ButtonText, and ButtonSubText. All are string.
What I want to do is bind the control in such a way that MemberCount is bound to the ButtonText property on one control, and EventCount is Bound to ButtonText property on another control.
So I do something along the lines of:
<control:MyControl ... ButtonText="{Binding MemberCount, Mode=OneWay}" ButtonSubText="Members" Background="{DynamicResource MetroRed}" />
The DataContext of my window is set to the correct ViewModel.
No matter what I try, I cannot get the member count or event count to show up on the control. I get an error in the output window:
System.Windows.Data Error: 40 : BindingExpression path error: 'MemberCount' property
not found on 'object' ''MyControl' (Name='button')'. BindingExpression:Path=MemberCount;
DataItem='MyControl' (Name='button'); target element is 'MyControl' (Name='button');
target property is 'ButtonText' (type 'String')
I am getting used to DataBinding in WPF, but for the life of me, I can't figure this one out.
What do I need to do to be able to bind a property from my view model to a property on my custom control?
i think the problem is the datacontext or binding within your usercontrol. you should post your usercontrol code.
<MyUserControl x:Name="uc">
<TextBlock Text="{Binding ElementName=uc,Path=ButtonText}/>
</MyUserControl>
check my answer here, there is a similar problem.

WPF Binding to Window property failing

I've got a custom control class in my project called "CarSystemWindow". It descends from Window and has a custom template that gives all windows in my application the same look. It also defines two dependency properties named DeviceName and DeviceType. These are of type string. They default to "Vehicle: " and "Car 54", respectively.
In my main program, I retrieve a row from my database into a View Model object and save that in a normal CLR property called Site during the program's initialization. In the MainWindow's xaml, I have the following code:
<cs:CarSystemWindow x:Class="....MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:..."
xmlns:cs="..."
Background="Black"
Closed="Window_Closed"
DataContext="{Binding Path=Site, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
DeviceName="{Binding Path=SiteName}"
DeviceType="{Binding Path=SiteTypeName}"
Icon="..."
Height="600"
Loaded="Window_Loaded"
ResizeMode="CanMinimize"
SourceInitialized="Window_SourceInitialized"
Title="Window Title"
Width="800"
WindowStartupLocation="CenterScreen">
At run time, the binding on the DataContext attribute is failing with the following message:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=Site; DataItem=null; target element is 'MainWindow' (Name=''); target property is 'DataContext' (type 'Object')
I'm using this same binding code elsewhere and it works. I've even turned the Site property into a dependency property and its still failing.
Does anyone give have ideas why the binding is failing?
Thanks
Tony
I think you need to change your binding to this:
{Binding RelativeSource={RelativeSource Self}, Path=Site}
The reason your current binding is not working is that you are trying to go up a level in the hierarchy from the Window, but you actually want the Window.
Here is a good source for figuring out what the binding string should be for different scenarios:
http://www.nbdtech.com/Free/WpfBinding.pdf
The problem with the DataContext binding is that the line is saying to use the Site property on an object that is an ancestor of this object, and of type Window. Since this object is a Window already, and therefore at the root of the visual tree, there are no ancestors to search and find the specified property.
Why don't you assign the DataContext where this object is constructed?

Setting DataContext makes PropertyChanged null in UserControl

I have a WPF application which uses a WPF user control.
The user control exposes a DependencyProperty to which I would like to bind to in my WPF application.
As long as my user control does not set its own DataContext this works and I am able to listen to changes in the DependencyProperty.
However the moment I set the DataContext the PropertyChanged being called is null.
What am I missing here?
Code sample:
https://skydrive.live.com/redir.aspx?cid=367c25322257cfda&page=play&resid=367C25322257CFDA!184
DependencyProperty has inheritance property, so if you don't set the UserControlDP's DataContext, the DataContext is inherited from the MainWindow's DataContext. In this case, the UserControlDP's DataContext in your code below is set as MainWindow_ViewModel. Thus, the binding is correctly executed.
<usercontrol:UserControlDP Width="200" Height="100"
TestValue="{Binding TestValueApp, Mode=TwoWay, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}"
Margin="152,54,151,157"></usercontrol:UserControlDP>
In the other case, UserControlDP's DataContext is set as UserControlDP_ViewModel, so the binding is broken. You can see the first exception message as the following at the debug window.
System.Windows.Data Error: 40 : BindingExpression path error: 'TestValueApp' property not found on 'object' ''UserControlDP_ViewModel' (HashCode=24672987)'. BindingExpression:Path=TestValueApp; DataItem='UserControlDP_ViewModel' (HashCode=24672987); target element is 'UserControlDP' (Name=''); target property is 'TestValue' (type 'Object')
Consider setting the DataContext on one of the elements contained within UserControl rather than on UserControl itself.
Thanks for the input and clarifying the details.
After giving it some thought I took the easy way out and removed the ViewModel from the control.
MVVM for the application but no MVVM for the user control.
This way I do not use any bindings in the user control, instead use Dependency Properties which are bound to in the Main application.

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.

Binding to properties outside of the datacontext

I am creating a WPF application and am having a little difficulty implementing an user interface idea I have.
I have a MasterViewModel bound to the MainWindow which exposes an observable collection of ViewModels. I have written some commands that essentially switch the current view model in the observable collection and this subsequently displays the corresponding view. However, when the application first loads, I add a HomeViewModel to the collection which shows the Home (Navigation) View. The problem I am having is the Commands I am binding against are exposed on the MasterViewModel so they aren't 'cascading' into the items control. Can anyone offer a solution or a better one? Many Thanks.
This is the error I am receiving:
System.Windows.Data Error: 40 :
BindingExpression path error:
'MainWindowViewModel' property not found on 'object' ''HomeViewModel' (HashCode=5313339)'. BindingExpression:Path=MainWindowViewModel.LoadClientsCommand;
DataItem='HomeViewModel' (HashCode=5313339);
target element is 'Button' (Name='');
target property is 'Command' (type 'ICommand')
I believe you can access commands on the DataContext of your MasterViewModel through RelativeSource in the following way:
<Button>
<Button.Command>
<Binding Path="DataContext.MasterViewCommand">
<Binding.RelativeSource>
<RelativeSource
Mode="FindAncestor"
AncestorType="{x:Type MasterViewBaseClass}"
/>
</Binding.RelativeSource>
</Binding>
</Button.Command>
Click me!
</Button>
Can you provide code examples of your code scenario?
This reminds me of Josh Smith's MVVM example (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx), mb you got your idea from there?
If I understand you correctly: Why don't you write a VM for your ItemControl and put your commands in there?
You could try to access the Commands from your ItemControl via RelativeSource (How do I use WPF bindings with RelativeSource?)

Resources