7

I have the following XAML:

<UserControl x:Class="WpfWindow.MyControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">
  <UserControl.RenderTransform>
    <TranslateTransform X="{Binding ElementName=MySlider, Path=ActualWidth}" />
  </UserControl.RenderTransform>
  <Grid>
    <Slider x:Name="MySlider" Canvas.Left="41" Canvas.Top="86" Height="23"  Width="100" Minimum="0" Maximum="100"/> 
  </Grid>
</UserControl>

When I try to use a window with the UserControl inside I get:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=MySlider'. BindingExpression:Path=ActualWidth; DataItem=null; target element is 'TranslateTransform' (HashCode=53368240); target property is 'X' (type 'Double')

It is especially strange since using the same code directly in a Window works flawlessly.

For now I've resolved the issue by setting the binding in code, however, I have no idea why my version doesn't work and I'd rather have everything in XAML if possible.

Thanks!

VitalyB
  • 12,397
  • 9
  • 72
  • 94

2 Answers2

8

I've noticed that sometimes when setting Bindings with ElementName on Window/UserControl etc. the order of declaration is important. I'm not sure of the reason for this but if you declare the Grid before you set <UserControl.RenderTransform> I think it'll work

<UserControl ...>
    <Grid Background="Red">
        <Slider x:Name="MySlider" Canvas.Left="41" Canvas.Top="86" Height="23"  Width="100" Minimum="0" Maximum="100"/>
    </Grid>
    <UserControl.RenderTransform>
        <TranslateTransform X="{Binding ElementName=MySlider, Path=ActualWidth}" />
    </UserControl.RenderTransform>
</UserControl>
Fredrik Hedblad
  • 83,499
  • 23
  • 264
  • 266
  • 1
    Weird, but works! Thanks! P.S I wish there were less of those "strange WPF quirks" :| – VitalyB Feb 20 '11 at 11:20
  • 2
    I also got this problem but regarding an attached property. If the target for the attached property is on the root element you need to expand the XAML to an element instead of an attribute. Example: [link](http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/78540874-ebde-43bb-99bd-002c0cf44308#eacbab17-62fb-4048-9103-1dcb3581fe40) – Johan Andersson Aug 18 '11 at 09:32
1

I actually have sort of similar issue and would like to share my solution.

I have set of shaders, which I want to apply to the borders. Shader's properties binded to the control's values (slider value).

XAML:

<Window.Resources>
    <ResourceDictionary>
        <Shaders:BrightnessContrastEffect x:Key="brightnessContrastEffect" Contrast="{Binding ElementName=SliderContrast, Path=Value}" Brightness="{Binding ElementName=SliderBrightness, Path=Value}" />
        <Shaders:SaturationHueEffect x:Key="saturationHueEffect" Hue="{Binding ElementName=SliderHue, Path=Value}" Saturation="{Binding ElementName=SliderSaturation, Path=Value}"/>
        <Shaders:SharpenEffect x:Key="sharpenEffect" Amount="{Binding ElementName=SliderSharpen, Path=Value}" />
    </ResourceDictionary>
</Window.Resources>

...

<StackPanel Name="PanelImage" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" SizeChanged="PanelImage_SizeChanged">
    <Border Effect="{StaticResource brightnessContrastEffect}">
        <Border Effect="{StaticResource saturationHueEffect}">
            <Border Effect="{StaticResource sharpenEffect}">
                <Border Name="PanelShaderInvert">
                    <Viewbox Stretch="Fill" MinHeight="400" MinWidth="640">
                        <dz:MultiScaleImage Name="ImageViolation" MinHeight="400" MinWidth="640"
                                            Source="{Binding ElementName=MyPath, Path=Content}"
                                            MouseLeftButtonDown="ImageViolationMouseLeftButtonDown"
                                            MouseLeftButtonUp="ImageViolationMouseLeftButtonUp"
                                            MouseRightButtonUp="ImageViolationMouseRightButtonUp" MouseMove="ImageViolation_MouseMove" />
                    </Viewbox>
                </Border>
            </Border>
        </Border>
    </Border>
</StackPanel>
<GridSplitter HorizontalAlignment="Right" VerticalAlignment="Stretch" Grid.Column="1" ResizeBehavior="PreviousAndNext" Width="0" />
<StackPanel Grid.Column="2" Grid.Row="0" Height="250" VerticalAlignment="Top">
    <Label Content="Brightness:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderBrightness" Minimum="-1" Maximum="1" Value="0" Margin="8,0" LargeChange="0.4" SmallChange="0.4" TabIndex="1" />
    <Label Content="Contrast:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderContrast" Maximum="2" Value="1" Margin="8,0" LargeChange="0.4" SmallChange="0.4" TabIndex="2" />
    <Label Content="Hue:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderHue" Maximum="359" Margin="8,0" LargeChange="72" SmallChange="72" TabIndex="3" />
    <Label Content="Saturation:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderSaturation" Maximum="5" Value="1" Margin="8,0" LargeChange="1" SmallChange="1" TabIndex="4" />
    <Label Content="Sharpen:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderSharpen" Maximum="2" Value="0" Margin="8,0" LargeChange="0.4" SmallChange="0.4" TabIndex="5" />
    <CheckBox Name="CheckBoxInvertColours" Content="Invert Colours" Margin="8" Checked="CheckBoxInvertColoursChecked" Unchecked="CheckBoxInvertColoursUnchecked" TabIndex="6" />
</StackPanel>

Works perfectly while in Window, but after I moved that XAML to the User Control it just stop working.

You cannot move Window.Resources to the bottom of the user control.

So, solution, which works for me was to assign resources right in the container (Border in my case) instead of referencing them from the Resource section:

<StackPanel Name="PanelImage" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" SizeChanged="PanelImage_SizeChanged">
    <Border>
        <Border.Effect>
            <Shaders:BrightnessContrastEffect Contrast="{Binding ElementName=SliderContrast, Path=Value}" Brightness="{Binding ElementName=SliderBrightness, Path=Value}" />
        </Border.Effect>
        <Border>
            <Border.Effect>
                <Shaders:SaturationHueEffect Hue="{Binding ElementName=SliderHue, Path=Value}" Saturation="{Binding ElementName=SliderSaturation, Path=Value}"/>
            </Border.Effect>
            <Border>
                <Border.Effect>
                    <Shaders:SharpenEffect Amount="{Binding ElementName=SliderSharpen, Path=Value}" />
                </Border.Effect>
                <Border Name="PanelShaderInvert">
                    <Viewbox Stretch="Fill" MinHeight="400" MinWidth="640">
                        <dz:MultiScaleImage Name="ImageViolation" MinHeight="400" MinWidth="640"
                                                                    Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:ImageControl, AncestorLevel=1}, Path=ImageSource}"
                                                                    MouseLeftButtonDown="ImageViolationMouseLeftButtonDown"
                                                                    MouseLeftButtonUp="ImageViolationMouseLeftButtonUp"
                                                                    MouseRightButtonUp="ImageViolationMouseRightButtonUp" MouseMove="ImageViolation_MouseMove" />
                    </Viewbox>
                </Border>
            </Border>
        </Border>
    </Border>
</StackPanel>
<GridSplitter HorizontalAlignment="Right" VerticalAlignment="Stretch" Grid.Column="1" ResizeBehavior="PreviousAndNext" Width="0" />
<StackPanel Grid.Column="2" Grid.Row="0" Height="250" VerticalAlignment="Top">
    <Label Content="Brightness:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderBrightness" Minimum="-1" Maximum="1" Value="0" Margin="8,0" LargeChange="0.4" SmallChange="0.4" TabIndex="1" />
    <Label Content="Contrast:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderContrast" Maximum="2" Value="1" Margin="8,0" LargeChange="0.4" SmallChange="0.4" TabIndex="2" />
    <Label Content="Hue:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderHue" Maximum="359" Margin="8,0" LargeChange="72" SmallChange="72" TabIndex="3" />
    <Label Content="Saturation:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderSaturation" Maximum="5" Value="1" Margin="8,0" LargeChange="1" SmallChange="1" TabIndex="4" />
    <Label Content="Sharpen:" Style="{StaticResource DoubleLineLayoutLabel}" />
    <telerik:RadSlider Name="SliderSharpen" Maximum="2" Value="0" Margin="8,0" LargeChange="0.4" SmallChange="0.4" TabIndex="5" />
    <CheckBox Name="CheckBoxInvertColours" Content="Invert Colours" Margin="8" Checked="CheckBoxInvertColoursChecked" Unchecked="CheckBoxInvertColoursUnchecked" TabIndex="6" />
</StackPanel>

I believe this is a bug, but at least there is workaround.

Anri
  • 11
  • 2
  • Interesting. However, that way you can't reuse the resources... What about putting the shaders into the resource property of the StackPanel. Would it work? – VitalyB Mar 10 '11 at 22:13
  • Never thought about that. Going to try. Thank you for the idea! – Anri Mar 11 '11 at 22:56