Binding to properties outside of the datacontext - wpf

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?)

Related

Wpf usercontrol dependency Property Binding

In my mainwindow I have got an UserControl, which ViewModel has got the Dependency Property "Message", I'm trying to bind the Dependency Property to an Property of the ViewModel of the Main Window, but actually it isn't Working, is there any soulution or is it genarally impossible?
Content of the Main Window:
<local:MessageLayer>
<local:MessageLayer.DataContext>
<local:MessageBoxViewModel Message="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext.Message}"/>
</local:MessageLayer.DataContext>
</local:MessageLayer>
View models should not have DependencyPropertys in them and should certainly not extend the DependencyObject class, because these are UI related classes. I'm sure that you, along with many others have been confused by Microsoft's terribly worded error below:
A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
This is really only referring to the UI element side of Bindings and not the data element side. For data binding data objects, we implement the INotifyPropertyChanged interface instead, which provides similar property change notification functionality to DependencyPropertys.
So, had you set the Window.DataContext to an instance of a view model that implemented INotifyPropertyChanged, with a property declared in it named Message, then your code would have worked just fine:
<local:MessageLayer>
<local:MessageLayer.DataContext>
<local:MessageBoxViewModel Message="{Binding RelativeSource={RelativeSource
AncestorType=Window, Mode=FindAncestor}, Path=DataContext.Message}"/>
</local:MessageLayer.DataContext>
</local:MessageLayer>

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.

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

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.

Resources