自定义 WPF 控件中的数据绑定
Data binding in custom WPF controls
我完全无法尝试将图像绑定到我的自定义 WPF 扩展器。
我在这里找到了创建扩展器模板的示例:https://www.codeproject.com/Articles/248112/Templating-WPF-Expander-Control 并尝试对其进行编辑以使用图像而不是扩展器图标。
这是我的扩展按钮自定义模板(我在这里添加了一个图像源,因此它可以在直接资源路径下正常工作,而不是绑定):
<ControlTemplate x:Key="SimpleExpanderButtonTemp"
TargetType="{x:Type ToggleButton}">
<Border x:Name="ExpanderButtonBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image
Height="35"
Width="35"
Source="{Binding Path = ImageSource,
RelativeSource={RelativeSource TemplatedParent}}">
</Image>
<ContentPresenter x:Name="HeaderContent"
Grid.Column="1"
Margin="4,0,0,0"
ContentSource="Content"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<!-- MouseOver, Pressed behaviours-->
<Trigger Property="IsMouseOver"
Value="true">
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
之后,我将模板添加到扩展器本身:
<ControlTemplate x:Key="SidePanelExpander" TargetType="Expander">
<DockPanel>
<ToggleButton x:Name="ExpanderButton"
DockPanel.Dock="Top"
ImageSource="{Binding Path = ImageSource,
RelativeSource={RelativeSource TemplatedParent}}"
Template="{StaticResource SimpleExpanderButtonTemp}"
Content="{TemplateBinding Header}"
IsChecked="{Binding Path=IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
Padding="1.5,0">
</ToggleButton>
<ContentPresenter x:Name="ExpanderContent"
Visibility="Collapsed"
DockPanel.Dock="Bottom"/>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter TargetName="ExpanderContent"
Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
然后我尝试以这种方式使用它:
<Expander ExpandDirection="Right"
Template="{StaticResource SidePanelExpander}"
ImageSource="../Res/Images/engine.png"
>
我猜想通过模板进行数据绑定转发有一些困难,但不知道如何解决。
正如 Clemens 在评论中所说,ToggleButton
和 Expander
没有一个名为 ImageSource 的 属性,因此此代码永远无法工作。执行此操作的“正确”方法是创建自定义控件,但快速修复(hack)是使用标签 属性:
指定图像路径
在“SimpleExpanderButtonTemp”模板中,按如下方式更改 Image
元素源:
<Image Height="35"
Width="35"
Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" />
接下来,在“SidePanelExpander”模板 ToggleButton 中,删除“ImageSource=...”行并将其替换为:
Tag="{TemplateBinding Tag}"
最后,在控件本身中,指定您的图像:
<Expander Tag="../Res/Images/engine.png"
...
此外,在第一个模板中,我注意到您在 Border
控件的某些属性(背景、边框刷、边框厚度)上使用了 TemplateBindings。这些也行不通。要解决此问题,请将这些相同的行复制到第二个模板的 ToggleButton
控件,即
<ToggleButton x:Name="ExpanderButton"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
...
您现在可以在控件本身中指定(比方说)背景颜色:
<Expander Background="Blue"
...
ToggleButton 上的 TemplateBindings 就像垫脚石,允许 属性 值从控件本身传递到 ToggleButton,然后传递到 Border。
我完全无法尝试将图像绑定到我的自定义 WPF 扩展器。
我在这里找到了创建扩展器模板的示例:https://www.codeproject.com/Articles/248112/Templating-WPF-Expander-Control 并尝试对其进行编辑以使用图像而不是扩展器图标。
这是我的扩展按钮自定义模板(我在这里添加了一个图像源,因此它可以在直接资源路径下正常工作,而不是绑定):
<ControlTemplate x:Key="SimpleExpanderButtonTemp"
TargetType="{x:Type ToggleButton}">
<Border x:Name="ExpanderButtonBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image
Height="35"
Width="35"
Source="{Binding Path = ImageSource,
RelativeSource={RelativeSource TemplatedParent}}">
</Image>
<ContentPresenter x:Name="HeaderContent"
Grid.Column="1"
Margin="4,0,0,0"
ContentSource="Content"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<!-- MouseOver, Pressed behaviours-->
<Trigger Property="IsMouseOver"
Value="true">
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
之后,我将模板添加到扩展器本身:
<ControlTemplate x:Key="SidePanelExpander" TargetType="Expander">
<DockPanel>
<ToggleButton x:Name="ExpanderButton"
DockPanel.Dock="Top"
ImageSource="{Binding Path = ImageSource,
RelativeSource={RelativeSource TemplatedParent}}"
Template="{StaticResource SimpleExpanderButtonTemp}"
Content="{TemplateBinding Header}"
IsChecked="{Binding Path=IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
Padding="1.5,0">
</ToggleButton>
<ContentPresenter x:Name="ExpanderContent"
Visibility="Collapsed"
DockPanel.Dock="Bottom"/>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter TargetName="ExpanderContent"
Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
然后我尝试以这种方式使用它:
<Expander ExpandDirection="Right"
Template="{StaticResource SidePanelExpander}"
ImageSource="../Res/Images/engine.png"
>
我猜想通过模板进行数据绑定转发有一些困难,但不知道如何解决。
正如 Clemens 在评论中所说,ToggleButton
和 Expander
没有一个名为 ImageSource 的 属性,因此此代码永远无法工作。执行此操作的“正确”方法是创建自定义控件,但快速修复(hack)是使用标签 属性:
在“SimpleExpanderButtonTemp”模板中,按如下方式更改 Image
元素源:
<Image Height="35"
Width="35"
Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" />
接下来,在“SidePanelExpander”模板 ToggleButton 中,删除“ImageSource=...”行并将其替换为:
Tag="{TemplateBinding Tag}"
最后,在控件本身中,指定您的图像:
<Expander Tag="../Res/Images/engine.png"
...
此外,在第一个模板中,我注意到您在 Border
控件的某些属性(背景、边框刷、边框厚度)上使用了 TemplateBindings。这些也行不通。要解决此问题,请将这些相同的行复制到第二个模板的 ToggleButton
控件,即
<ToggleButton x:Name="ExpanderButton"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
...
您现在可以在控件本身中指定(比方说)背景颜色:
<Expander Background="Blue"
...
ToggleButton 上的 TemplateBindings 就像垫脚石,允许 属性 值从控件本身传递到 ToggleButton,然后传递到 Border。