System.Windows.Data Error: 40 : BindingExpression path error: - c#

Really annoying issue. The code seems to work fine, but when run, I see this error being thrown up:
System.Windows.Data Error: 40 : BindingExpression path error: 'IsOpen'
property not found on 'object' ''MainViewModel' (HashCode=33664731)'.
BindingExpression:Path=IsOpen; DataItem='MainViewModel'
(HashCode=33664731); target element is 'Popup' (Name='LoginPopup');
target property is 'IsOpen' (type 'Boolean')
I understand there is some sort of issue where IsOpen property of LoginPopup binding is being attempted on the MainViewModel and failing because there is no IsOpen property in the MainViewModel. Fine and good, but the DataContext I'm binding to is not the mainviewmodel, but the LoginPopupViewModel (LoginPopup in the ViewModelLocator class). Intellisense seems to agree with me that things are bound to the LoginPopupViewModel, as if I type other things in the Binding portion of IsOpen, it complains that, "Cannot resolve property in data context of LoginPopupViewModel", as it should.
Here's a portion of the XAML code:
<Popup x:Name="LoginPopup" PlacementTarget="{Binding ElementName=LoginButton}"
Placement="Bottom"
HorizontalOffset="-40" VerticalOffset="35" StaysOpen="False"
IsOpen=" {Binding IsOpen}"
DataContext="{Binding LoginPopup, Mode=OneWay, Source={StaticResource Locator}}"
Grid.ColumnSpan="3" Grid.Column="0"
Margin="0,0,0.333,0"
Grid.Row="0" Grid.RowSpan="2">
I'm not exactly a master of WPF, so I'm probably missing something, or the sytax is wrong here. Any help would be fantastic! Thanks!

You are getting that error because DataContext binding is afterIsOpen binding, so when the parser comees across IsOpen the DataContext is currently MainViewModel (set by dependency property inheritance). Then WPF processes the DataContext={..} and re-evaluated the IsOpen binding.
E.g. 2 bindings ultimately the same, but one showing an error
This gives an error in output, but works
<TextBlock Text="{Binding TextB}" DataContext="{Binding B}"></TextBlock>
This doesn't give error
<TextBlock DataContext="{Binding B}" Text="{Binding TextB}"></TextBlock>
Original Answer
The error you are getting is because this:
IsOpen="{Binding IsOpen}"
cannot be bound successfully.
You are binding the DataContext of it to {StaticResource Locator}, and a property LoginPopup on that resource. I am assuming Locator.LoginPopup return a MainViewModel?
What is Locator.LoginPopup and what are you trying to achieve by IsOpen="{Binding IsOpen}"? Is that a property on some view model?

Related

DataContext of a XAML ComboBox Not Working

I have a WPF ComboBox created in XAML:
<ComboBox DockPanel.Dock="Top" Background="{DynamicResource Esri_BackgroundPressedBrush}" DataContext="DockpaneData"
Foreground="{DynamicResource Esri_TextMenuBrush}" HorizontalAlignment="Stretch" FontSize="14" VerticalAlignment="Center" Margin="5,0,5,0" IsEditable="True" Text="Jump To"
ItemsSource="{Binding FeatureEditUpdates}">
</ComboBox>
I set the DataContext of the ComboBox "DockpaneData", which in this case is an internal class called "DockpaneData" within another file called DockpaneViewModel.cs.
Why Can't I bind to the public class property "FeatureEditUpdates"?
It will work if I put it in the class with the same name as the file, and DON'T set the datacontext in the ComboBox. Why?
The error I'm getting in the output window is:
System.Windows.Data Error: 40 : BindingExpression path error: 'FeatureEditUpdates' property not found on 'object' ''String' (HashCode=-1567065443)'. BindingExpression:Path=FeatureEditUpdates; DataItem='String' (HashCode=-1567065443); target element is 'ComboBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
Where I see it thinks the datacontext is a string, which doesn't make sense to me.
Thank you!
The expression
<ComboBox ... DataContext="DockpaneData"/>
sets the DataContext of the ComboBox to the string literal "DockpaneData", which you see in the error message
property not found on 'object' ''String'
One way to set the DataContext correctly is to declare and use a XAML resource:
<Window.Resources>
<local:DockpaneData x:Key="DockpaneData"/>
</Window.Resources>
...
<ComboBox ... DataContext="{StaticResource DockpaneData}"/>

Custom control binding is not updating

I'm having trouble getting my binding to work correctly. Basically I have this, call this Control1.xaml. The commented out portion of the code binds correctly and updates as expected.
<progControls:CalibrationSummary
</progControls:CalibrationSummary>
<!--<TextBlock Text="{Binding Path=NumberOfCalibrations, Mode=OneWay}"/>-->
However, if I put that commented code in a custom control called CalibrationsSummary.xaml, I cannot bind this to NumberOfCalibrations.
Here's what CalibrationsSummary looks like
<Grid>
<TextBlock Text="{Binding Path=NumberOfCalibrations, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
Note that I do use RelativeSource to try to get the property associated with Control1.xaml, tried TemplateBinding also. What am I doing wrong?
CalibrationSummary has no TemplatedParent unless you have put it in a ControlTemplate.
If you don't explicitly set the DataContext of the property of CalibrationSummary somewhere, it will inherit the DataContext from its parent control (which I assume is Control1) and then you can bind any property of this control's DataContext as usual without specifying any source:
<Grid>
<TextBlock Text="{Binding Path=NumberOfCalibrations}"/>
</Grid>

How to set DataContext to self

My UserControl requires binding to the ancestor (the ancestor being the MainWindow) and to itself (it's code behind).
To bind to the ancestor, I'm using
DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1,AncestorType=Window}}">
To bind a control to the code behind (and thus using the 'local' DataContext), I'm using
<TextBlock Text ="{Binding MyUC3Property}" Name="MyName" />
and in the code behind, setting it like
this.MyName.DataContext = this;
The above works fine, where I can bind to the codebehind and to the ancestor.
Now, I still want to bind to the code behind and the ancestor but set the DataContext in the XAML only (if possible).
I've tried
<TextBlock Text ="{Binding MyUC3Property}" DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}" />
and ensured the constructor does not set the DataContext (since I want it all done in the XAML) - (although even if I do set this.DataContext = this; the error persists)
and the output window tells me there is a binding error.
System.Windows.Data Error: 40 : BindingExpression path error: 'MyUC3Property' property not found on 'object' ''TextBlock' (Name='')'. BindingExpression:Path=MyUC3Property; DataItem='TextBlock' (Name=''); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
I guess I'm missing something obvious, but I can't tell what.
You should be able to bind to the user control the same way as you do to the window:
DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1,AncestorType=UserControl}}">
What you have tried was referring to the relative source Self from the TextBox. However, in that context, Self refers to the TextBox, not to the enclosing user control.
for usercontrols you should never set the datacontext to self. check to comment from H.B. from here
i use ElementName Binding
<UserControl x:Name="uc">
<TextBlock Text="{Binding ElementName=uc, Path=MyDependencyPropertyDefinedInMyUserControl}"/>
using the usercontrol:
<Window>
<MyUserControl MyDependencyPropertyDefinedInMyUserControl="{Binding Path=MyValueForTheTextBox}"/>
i try to explain it a little bit for your textbox case (ignor my poor english btw :))
if you want create a usercontrol with a textbox and this usercontrol/textbox should show the text from differrent viewmodels in different views - then you have a problem as far as the viewmodels have different propertynames. now the dependency property in your usercontrol come into the game. you create a DP where all your viewmodels can bind to and you bind your textbox within your usercontrol just to the DP from your usercontrol.
First thing is that you should probably push your parent DataContext to the lower levels. This will give you "God" ViewMode shared between all nested screens.
Second is that you should probably use something like MVVMLights Messanger to have cleaner separation.

Strange BindingExpression path error with ContentPresenter

In my program I have a mainWindow that contains a contentPresenter. The mainWindow has a ViewModel called MainWindowViewModel. This viewModel contains properties that are bound to items in the mainWindow.
The Content of my contentPresenter is represented by a UserControl->ViewModel->Model structure.
This is the xaml of the contentPresenter that I am working with.
MainWindow.xaml:
<ContentPresenter Content="{Binding LeftWidget}" IsEnabled="{Binding LeftWidgetEnabled}" ... />
LeftWidget and LeftWidgetEnabled are both properties located in MainWindowViewModel. However, the BindingExpression path error that I receive has to do with LeftWidgetEnabled. For some reason my program is looking for the property in the ViewModel of the contentPresenter's UserControl. This doesn't make much sense to me, because the program deals with the LeftWidget property correctly.
Both properties are located in MainWindowViewModel, so why would the program be looking elsewhere for the LeftWidgetEnabled property? How can I fix this?
Also Note: The way that I set the DataContext of my UserControls are like so...
Under <Window.Resources... in mainWindow.xaml:
<DataTemplate DataType="{x:Type project:LeftWidgetViewModel}">
<local:LeftWidgetUserControl/>
</DataTemplate>
chnage the binding path to (this assumes main window is in fact a window object):
IsEnabled={Binding DataContext.LeftWidgetEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}
does that help? If so then you need to examine the datacontext of your objects as there might be something else going on
also, does the datatype of LeftWidgetEnabled match what is expected by the IsEnabled Property, ie boolean to boolean?
if LeftWidget and LeftWidgetEnabled are in the same datacontext and if LeftWidget is working. then i would say you should check your property in your viemodel wether its really LeftWidgetEnabled.
the xaml looks good for me.
EDIT: LeftWidgetEnabled should be typeof bool not bool?

WPF Element Binding with ContextMenu

In WPF I have the following structure:
UserControl > Grid > TabControl > DataGrid > ContextMenu
I would like to have the DataContext of my ContextMenu the same as the one for my Grid. This is how I am currently trying to do it:
<ContextMenu Name="contextMenu" DataContext="{Binding ElementName=MainGrid, Path=DataContext}">
But I get the following error:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=MainGrid'. BindingExpression:Path=DataContext; DataItem=null; target element is 'ContextMenu' (Name='contextMenu'); target property is 'DataContext' (type 'Object')
I need to do it this way as the DataContext of the DataGrid is different from the "MainGrid", and the ContextMenu is in the DataGrid.
Can anyone offer me some guidance as according to me this is correct?
I feel that is not required. The DataContext set at the parent level is already available to the child. You can override, if you need. But in your case you want to use the same Datacontext.
normally you would bind a property to your specific DataContext, and not the DataContext itself to another DataContext. But in your case, this should help:
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=DataContext}"

Categories

Resources