c# - WPF - ContentPresenter 不绑定(bind)到 UserControl 内容

标签 c# wpf xaml user-controls blend

好吧,我是 WPF 的新手,我的包含自定义按钮的用户控件有点问题。

一切正常,直到我尝试将自定义按钮的内容绑定(bind)到用户控件内容。

用户控制代码:

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:OP"
mc:Ignorable="d"
x:Class="OP.GamepadButton"
x:Name="GamePadBtn"
d:DesignWidth="100" d:DesignHeight="100">
<UserControl.Resources>
    <Style x:Key="GamepadButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <Rectangle x:Name="rectangle" Fill="{TemplateBinding Background}" StrokeThickness="1" Opacity="0.8" Stroke="{TemplateBinding BorderBrush}"/>
                        <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                        RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsFocused" Value="True"/>
                        <Trigger Property="IsDefaulted" Value="True"/>
                        <Trigger Property="IsMouseOver" Value="True"/>
                        <Trigger Property="IsPressed" Value="True"/>
                        <Trigger Property="IsEnabled" Value="False"/>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Button Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GamepadButton}}, Path=Content}" 
    Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GamepadButton}}, Path=Background}" 
    BorderBrush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GamepadButton}}, Path=BorderBrush}" 
    Grid.Row="1" Style="{DynamicResource GamepadButtonStyle}" />
</Grid>

然后我在主窗口中声明用户控件的方式如下:

<local:GamepadButton Height="60" Width="60" Background="#DAF0FC" BorderBrush="#2c3e50" Content="Button"/>

结果如下:

Result 1

另外,我现在注意到,出于某种原因,这也会破坏 BorderBrush 绑定(bind),但不会破坏 Background 绑定(bind)。


如果我不为 Usercontrol 声明任何内容属性并直接设置按钮内容,代码就可以工作:

用户控件:

<Button Content="Button" 
    Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GamepadButton}}, Path=Background}" 
    BorderBrush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GamepadButton}}, Path=BorderBrush}" 
    Grid.Row="1" Style="{DynamicResource GamepadButtonStyle}" />

主窗口:

<local:GamepadButton Height="60" Width="60" Background="#DAF0FC" BorderBrush="#2c3e50" />

这给了我想要的按钮样式:

Result 2


所以我的问题是。

如何使按钮的 ContentPresenter 绑定(bind)到为用户控件声明的内容?

最佳答案

您面临的问题是您无法从内容内部绑定(bind)到内容。您在用户控件中的按钮是控件的当前内容。在您的输出窗口中,您会看到这一行

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='OP.GamepadButton', AncestorLevel='1''. BindingExpression:Path=Tag; DataItem=null; target element is 'Button' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='OP.GamepadButton', AncestorLevel='1''. BindingExpression:Path=Background; DataItem=null; target element is 'Button' (Name=''); target property is 'Background' (type 'Brush')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='OP.GamepadButton', AncestorLevel='1''. BindingExpression:Path=BorderBrush; DataItem=null; target element is 'Button' (Name=''); target property is 'BorderBrush' (type 'Brush')

如果您将其更改为其他属性,例如 Tag,那么您的样式将正确应用。

我认为你可以只使用样式来解决你的任务,但如果你真的需要新的 UserControl 那么你可以直接从按钮而不是 UserControl 继承它。

关于c# - WPF - ContentPresenter 不绑定(bind)到 UserControl 内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28917946/

相关文章:

c# - Visual Studio 将类型名称复制到剪贴板

使用 Discord 机器人进行 C# 时间减法

c# - 如何在 XBAP 或 ClickOnce 应用程序中获取引荐来源网址?

c# - WPF Path/"up"箭头被截断 2px

Xaml 绑定(bind)到 Xamarin Forms 中的自定义类

如果监视目录在启动时不为空,C# 可以触发 FileSystemWatcher 吗?

javascript - 如何创建跨域HTTP请求

wpf - 使用 MediaElement 播放 .mp4 时的视觉瑕疵

c# - LoadFromContext 发生

c# - WPF:如何使用数据触发器(或等效项)交换 Listview 单元格内容