通过 ElementName 将 UserControl 属性绑定到其子属性会导致绑定错误

发布于 2024-10-18 04:09:48 字数 1271 浏览 2 评论 0原文

我有以下 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>

当我尝试使用内部包含 UserControl 的窗口时,我得到:

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

这特别奇怪,因为直接在 Window 中使用相同的代码可以完美地工作。

目前,我已经通过在代码中设置绑定解决了该问题,但是,我不知道为什么我的版本不起作用,如果可能的话,我宁愿将所有内容都放在 XAML 中。

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏花。依旧 2024-10-25 04:09:48

我注意到有时在 Window/UserControl 等上使用 ElementName 设置绑定时,声明的顺序很重要。我不确定这样做的原因,但如果您在设置 之前声明 Grid 我认为它会起作用

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

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>
冰雪之触 2024-10-25 04:09:48

我实际上有类似的问题,想分享我的解决方案。

我有一组着色器,我想将其应用于边框。
着色器的属性绑定到控件的值(滑块值)。

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>

在 Window 中工作得很好,但在我将该 XAML 移至用户控件后,它就停止工作了。

您无法将 Window.Resources 移动到用户控件的底部。

因此,对我有用的解决方案是在容器中分配资源(在我的例子中为边界),而不是从资源部分引用它们:

<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 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文