WPF - ContentPresenter 不绑定到 UserControl 内容
WPF - ContentPresenter does not bind to UserControl Content
好的,所以我是 WPF 的新手,我的包含自定义按钮的用户控件有点问题。
一切正常,直到我尝试将自定义按钮的内容绑定到用户控件内容。
用户控制代码:
<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"/>
结果如下:
此外,我现在注意到,出于某种原因,这也会破坏 BorderBrush 绑定,但不会破坏 Background 绑定。
如果我不为 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" />
这给了我想要的按钮样式:
所以我的问题是。
如何使按钮的 ContentPresenter 绑定到为用户控件声明的内容?
您面临的问题是您无法从内容内部绑定到该内容。您在用户控件中的按钮是控件的当前内容。在你的输出中 window 你会看到这一行
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。
好的,所以我是 WPF 的新手,我的包含自定义按钮的用户控件有点问题。
一切正常,直到我尝试将自定义按钮的内容绑定到用户控件内容。
用户控制代码:
<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"/>
结果如下:
此外,我现在注意到,出于某种原因,这也会破坏 BorderBrush 绑定,但不会破坏 Background 绑定。
如果我不为 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" />
这给了我想要的按钮样式:
所以我的问题是。
如何使按钮的 ContentPresenter 绑定到为用户控件声明的内容?
您面临的问题是您无法从内容内部绑定到该内容。您在用户控件中的按钮是控件的当前内容。在你的输出中 window 你会看到这一行
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。