WPF非依赖属性绑定的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF非依赖属性绑定的问题相关的知识,希望对你有一定的参考价值。
初学WPF,如图所示:
我想把MediaElement的Position属性绑定在MediaCurrentTs上面。
但是出现了一个Position不是依赖属性的异常。
我该怎么解决才能正常绑定呢?
依赖属性。Position不是它的依赖属性,不能用来做绑定。我的建议是,你可以继承MediaElement做个自定义控件,给自定义控件加个依赖属性,属性的回调函数中设置Positon。 参考技术A 使用附加属性,就像Cavas.Top一样 ,可以附加到其他控件上
WPF如何将附加属性绑定到依赖属性
【中文标题】WPF如何将附加属性绑定到依赖属性【英文标题】:WPF how to bind attached property to dependency property 【发布时间】:2020-12-22 10:45:24 【问题描述】:我正在自定义 DataGridCells,以便在角落有一个带有工具提示的小三角形。只有当工具提示有内容并且工具提示的内容将来自 DataGrid 的 ItemsSource 时,该三角形才应显示。
带有三角形的DataGrid:
现在我创建了一个名为 Hint 的附加属性,它将绑定到 ItemsSource 的属性,该属性将具有工具提示的内容。
public class HintAttachedProperty
public static void SetHint(DependencyObject obj, string text)
obj.SetValue(HintProperty, text);
public static string GetHint(DependencyObject obj)
return obj.GetValue(HintProperty)?.ToString() ?? string.Empty;
public static readonly DependencyProperty HintProperty =
DependencyProperty.RegisterAttached("Hint", typeof(string), typeof(HintAttachedProperty), new FrameworkPropertyMetadata(null));
DataGrid 的 xaml,现在附加的属性提示设置为值“A test”:
<local:CustomDataGrid x:Name="datagrid"
AutoGenerateColumns="False"
ItemsSource="Binding ItemsCollection"
ClipboardCopyMode="IncludeHeader"
EnableRowsMove="True"
AlternatingRowBackground="LightBlue"
AlternationCount="2">
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="IsChecked" Binding="Binding IsChecked"/>
<DataGridTextColumn x:Name="Test"
local:IsHighLightedAttachedProperty.IsHighLighted="True"
local:HintAttachedProperty.Hint="A test"
Header="ExperienceInMonth"
Binding="Binding ExperienceInMonth">
</DataGridTextColumn>
<DataGridTemplateColumn Header="References">
...
</DataGridTemplateColumn>
<DataGridTextColumn Header="EmployeeName" Binding="Binding EmployeeName"/>
<DataGridTextColumn Header="EmployeeAge" Binding="Binding EmployeeAge" />
</DataGrid.Columns>
</local:CustomDataGrid>
这里是 DataGridCell 的样式,它控制三角形的可见性,并且应该将附加属性绑定到工具提示的内容:
<Style TargetType="x:Type DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type DataGridCell">
<Border x:Name="borderSides" BorderThickness="2,0,2,0" Background="Transparent" BorderBrush="Transparent" SnapsToDevicePixels="True">
<Border x:Name="borderTopBottom" BorderThickness="0,2,0,2" Background="Transparent" BorderBrush="Transparent" SnapsToDevicePixels="True">
<Grid>
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" SnapsToDevicePixels="TemplateBinding SnapsToDevicePixels" />
<Polygon x:Name="pol" ToolTip="Binding RelativeSource=RelativeSource Self, Converter=StaticResource HintConverter" Grid.Column="1" HorizontalAlignment="Right" Points="5,0 10,0, 10,5" Stroke="Black" Fill="Black" >
</Polygon>
</Grid>
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="Binding RelativeSource=RelativeSource Self, Converter=StaticResource HintConverter" Value="x:Static sys:String.Empty">
<Setter TargetName="pol" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="Binding RelativeSource=RelativeSource Self, Converter=StaticResource HintConverter" Value="x:Null">
<Setter TargetName="pol" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
在绑定 Binding RelativeSource=RelativeSource Self, Converter=StaticResource HintConverter 我使用DataGridCell内容的转换器来获取附加属性的值,因为当我在做 Binding path=(local:HintAttachedProperty.Hint) 它总是返回 null。
转换器代码:
public class HintConverters : IValueConverter
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
DataGridCell dgc = value as DataGridCell;
if (dgc != null)
DataGridColumn col = dgc.Column;
if (col != null)
var hint = HintAttachedProperty.GetHint(col);
return hint;
return "";
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
throw new NotImplementedException();
调试时,我可以在转换器中看到值是“A test”,因此没有隐藏三角形,但是当我将光标放在工具提示上时为空:
提示值:
工具提示为空:
另一方面,如果我直接绑定到样式中 ItemsSource 的属性,例如 Employee Name,ToolTip="Binding EmployeeName" 效果很好:
如何将属性的值和附加属性绑定到属性?这可能吗?也许我应该换个方向?
感谢您的关注
【问题讨论】:
转换器是多余的,您只需要更正您的绑定以使其工作。
在Polygon
中,您需要找到DataGridCell
祖先,而不是Self
,因为那是多边形。从那里您需要访问Column
,因为这是Hint
所附加的。
<Polygon x:Name="pol" ToolTip="Binding Column.(local:HintAttachedProperty.Hint), RelativeSource=RelativeSource AncestorType=x:Type DataGridCell" Grid.Column="1" HorizontalAlignment="Right" Points="5,0 10,0, 10,5" Stroke="Black" Fill="Black"/>
在您的触发器中,相对来源是正确的,因为在这种情况下Self
是DataGridCell
,但如上所述,您需要访问附加了Hint
的Column
。
<DataTrigger Binding="Binding Column.(local:HintAttachedProperty.Hint), RelativeSource=RelativeSource Self" Value="x:Static system:String.Empty">
<Setter TargetName="pol" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="Binding Column.(local:HintAttachedProperty.Hint), RelativeSource=RelativeSource Self" Value="x:Null">
<Setter TargetName="pol" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
更新您的 cmets。在当前项目的数据上下文或数据网格数据上下文上绑定属性不起作用,因为列不是可视化树的一部分,因为列只是单元格如何定义在此列中应构造。
我将向您展示当前项目的数据上下文的解决方法。绑定到父 DataGrid
的数据上下文的工作方式不同。您可以通过Style
将Hint
属性附加到实际显示在单元格内的元素。在样式中,您可以访问当前项目的数据上下文。
如果您有一个只读列,您只需要创建一个ElementStyle
。如果您有一个要在其中显示多边形和工具提示的可编辑列,则还需要一个 EditingElementStyle
。
<DataGridTextColumn Header="EmployeeName" Binding="Binding EmployeeName">
<DataGridTextColumn.ElementStyle>
<Style TargetType="x:Type TextBlock" BasedOn="StaticResource x:Type TextBlock">
<Setter Property="local:HintAttachedProperty.Hint" Value="Binding EmployeeName"/>
</Style>
</DataGridTextColumn.ElementStyle>
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="x:Type TextBox" BasedOn="StaticResource x:Type TextBox">
<Setter Property="local:HintAttachedProperty.Hint" Value="Binding EmployeeName"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
调整绑定以使用Content
属性而不是Column
来访问您已将Hint
属性附加到的单元格模板中的***元素,例如TextBlock
.
<Polygon x:Name="pol" ToolTip="Binding Content.(local:HintAttachedProperty.Hint), RelativeSource=RelativeSource AncestorType=x:Type DataGridCell" Grid.Column="1" HorizontalAlignment="Right" Points="5,0 10,0, 10,5" Stroke="Black" Fill="Black" >
<DataTrigger Binding="Binding Content.(local:HintAttachedProperty.Hint), RelativeSource=RelativeSource Self" Value="x:Static system:String.Empty">
<Setter TargetName="pol" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="Binding Content.(local:HintAttachedProperty.Hint), RelativeSource=RelativeSource Self" Value="x:Null">
<Setter TargetName="pol" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
回顾一下,这里的主要问题是您无法从列访问数据上下文。
替代覆盖单元格ControlTemplate
的方法是创建DataGridTemplateColumn
s,在其中为每个列创建自定义DataTemplate
,其中包含箭头多边形和工具提示。
然后您可以轻松附加和绑定您的Hint
属性,因为您可以访问所有控件和当前项目的数据上下文。此解决方案的缺点是您必须为每一列创建自定义数据模板,并将箭头和工具提示 XAML 复制到任何地方。
【讨论】:
感谢您的回复!这在直接设置附加属性的值时确实有效,但如果我将它绑定到一个属性,它不会 local:HintAttachedProperty.Hint="Binding EmployeeName" @mmas 我为您的方案添加了两个解决方法。 谢谢!它确实有效,我一直在寻找一种更通用的方法,不必为每列创建自定义数据模板,但我会这样做以上是关于WPF非依赖属性绑定的问题的主要内容,如果未能解决你的问题,请参考以下文章