I have two controls within my UserControl where I bind to the exact same object using Element Binding:
AllowNext="{Binding ElementName=MainGrid, Path=DataContext.CanContinue}"
On the first control it works fine but on the second I get a binding exception:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=MainGrid'. BindingExpression:Path=DataContext.CanContinue; DataItem=null; target element is 'WizardPage' (Name='DeductionPage'); target property is 'AllowNext' (type 'Boolean')
I have also tried using RelativeSource binding on the second control:
AllowNext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}, Path=DataContext.CanContinue}"
But this also gives me an error.
Does anyone know what this might be?
--
Here is the simplified control:
<Grid Name="MainGrid">
<w:Wizard Name="MyWizard" w:Designer.PageIndex="1" DataContext="{Binding ElementName=MainGrid, Path=DataContext.Policy}" >
<w:WizardPage Header="Main Member" MaxHeight="600" AllowNext="{Binding ElementName=MainGrid, Path=DataContext.CanContinue}" Name="MainPage">
</w:WizardPage>
<w:WizardPage Name="DeductionPage" Header="Policy Details" AllowBack="False" AllowNext="{Binding ElementName=MainGrid, Path=DataContext.CanContinue}">
</w:WizardPage>
</w:Wizard>
</Grid>
Now as I mentioned, MainPage binds fine, whereas the DeductionPage does not bind at all and gets the supplied error. The DataContext of MainGrid is set from code behind:
public void SetDataContext(object o)
{
MainGrid.DataContext = o;
}
I bet it's the MainGrid which is the binding source is not in the logical tree of your binding target.
This is the problem absolutely with the binding element. However, you didn't give the source so You want to debug it and solve the issue.
Refer the below url and "Cannot find source for binding with reference" section where explained obviously how to debug and solve it.
http://www.codeproject.com/Articles/244107/Debugging-WPF-data-bindings
Related
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.
I have the following XAML:
<Grid>
<Grid.RowDefinitions>
...
</Grid.RowDefinitions>
<DataGrid Grid.Row="0" ...>
<DataGrid.Columns>
...
</DataGrid.Columns>
</DataGrid>
<DockPanel Grid.Row="2">
<CheckBox x:Name="DisplayMarkers" DockPanel.Dock="Top" Content="Display Data Points?"
Margin="8,5,0,5" d:LayoutOverrides="Height" HorizontalAlignment="Left" IsChecked="False" />
<vf:Chart DockPanel.Dock="Top" ScrollingEnabled="False" ZoomingEnabled="True" ToolBarEnabled="True">
<vf:DataSeries AxisYType="Secondary" RenderAs="Line" DataSource="{Binding CdTeRoughnessList}"
XValueType="DateTime"
MarkerEnabled="{Binding ElementName=DisplayMarkers, Path=IsChecked}" Color="Navy"
LegendText="Roughness Std. Dev.">
This binding is failing: MarkerEnabled="{Binding ElementName=DisplayMarkers, Path=IsChecked}"
I'm trying to bind to the IsChecked property on my Checkbox named 'DisplayMarkers". When I run this, in debug mode in VS 2010, the output window shows the binding is failing. It can't find the element named 'Checkbox'. Could anyone tell me why?
The error I'm getting from VS is:
System.Windows.Data Error: 4 : Cannot find source for binding with reference
'ElementName=DisplayMarkers'. BindingExpression:Path=IsChecked; DataItem=null; target element is 'DataSeries' (Name=''); target property is 'MarkerEnabled' (type 'Nullable`1')
You might not have a namescope where you try to bind, you could try to replace the ElementName construct with Source={x:Reference DisplayMarkers}.
The gist of it is that if you have elements in XAML which are not in the visual or logical tree you will not be able to use certain bindings like RelativeSource and ElementName, I suspect that DataSeries is not in any tree either (it sure sounds like it's abstract).
For a workaround for potential cyclical dependency errors see: https://stackoverflow.com/a/6858917/546730
I'm guessing that the writer of Chart, when deriving from FrameworkElement or whatever, failed to realize that they needed to add any child elements to the logical tree either manually or through an override. You don't get that for free when deriving.
Breaking the logical tree breaks the ability of children to bind by ElementName.
If you are the author of the Chart object, you can see this related question and answer.
For other readers, another possible cause is using a UserControl instead of a custom control for what's in the role of vf:Chart, above. I wrote a split button (in the role of the chart) and changing it from a UserControl to a custom control got my ElementName binding working.
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?
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.
I am trying to move custom DataGrid column definition into a UserControl.
MyComboBoxColumn.xaml
<dg:DataGridTemplateColumn
x:Class="WpfDecomposition.MyComboBoxColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"
x:Name="_this"
>
<dg:DataGridTemplateColumn.Header>
<Button Content="{Binding MyHeader, ElementName=_this}" ></Button>
</dg:DataGridTemplateColumn.Header>
</dg:DataGridTemplateColumn>
MyComboBoxColumn.cs
public partial class MyComboBoxColumn : DataGridTemplateColumn
{
public MyComboBoxColumn()
{
InitializeComponent();
}
public static DependencyProperty MyHeaderProperty =
DependencyProperty.Register("MyHeader", typeof(string), typeof(MyComboBoxColumn), new PropertyMetadata("TEST"));
}
Main windows XAML:
<dg:DataGrid CanUserAddRows="True" AutoGenerateColumns="False">
<dg:DataGrid.Columns>
<my:MyComboBoxColumn />
</dg:DataGrid.Columns>
</dg:DataGrid>
I would expect to see a button "TEST" in the column's header, but instead I see the empty button. Looks like the binding is broken. What is wrong?
It's not working because it can't find an element with the name _this. I get the following error in the Output window when I debug your code in Visual Studio:
System.Windows.Data Error: 4 : Cannot
find source for binding with reference
'ElementName=_this'.
BindingExpression:Path=MyHeader;
DataItem=null; target element is
'Button' (Name='TestButton'); target
property is 'Content' (type 'Object')
As for why it can't find it - I think that is because WPF bindings use the visual tree to find the source of the binding. In this case, the MyComboBoxColumn is not in the visual tree, so therefore it can't find an element with that name.
I also tried using RelativeSource to find the element, but that didn't work either - likely for the same reason.
The only thing that I could get to work is to set the DataContext of the button to the column itself in the constructor:
public MyComboBoxColumn()
{
InitializeComponent();
this.TestButton.DataContext = this;
}
And then change the binding in the XAML:
<tk:DataGridTemplateColumn.Header>
<Button Content="{Binding Path=MyHeader}" x:Name="TestButton" />
</tk:DataGridTemplateColumn.Header>
That doesn't seem like the best way to do it, but at least it works.
If you don't want to or can't set the DataContext in the constructor (e.g. when creting columns dynamically in the code), set the column's Header property to the object you want to bind to (the data context) and then you can bind to this object in the HeaderStyle data template.
See this question for details.