样式设置器中的 UWP 绑定不起作用
Posted
技术标签:
【中文标题】样式设置器中的 UWP 绑定不起作用【英文标题】:UWP Binding in Style Setter not working 【发布时间】:2016-02-08 00:30:46 【问题描述】:我在创建 xaml 控件时遇到问题。我正在通用应用程序中的 VS 2015 中编写新项目。我想创建网格。在这个网格中,我想要一个按钮。在模型中,我指定列(级别)和行。 这是我的代码:
<ItemsControl Grid.Row="1" ItemsSource="Binding Path=TechnologyList">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="Control">
<Setter Property="Grid.Column" Value="Binding Level" />
<Setter Property="Grid.Row" Value="Binding Row" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="Binding Name"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Setter Property="Grid.Column" Value="Binding Level" />
行出现错误
错误:来自 HRESULT 的异常:0x8000FFFF (E_UNEXPECTED) 在 edytor 中而不是在运行代码中。
怎么了?在“旧”WPF 中一切正常,但在适用于 Windows 10 的通用应用程序中出现错误。
谁能帮我 ?
【问题讨论】:
如何在 UWP 中做这样的事情? 【参考方案1】:如 MSDN 上Setter.Value property 页面上的迁移说明部分所述,UWP/Windows 运行时不支持样式设置器中的绑定。
Windows Presentation Foundation (WPF) 和 Microsoft Silverlight 支持使用绑定表达式提供值的能力 对于样式中的二传手。 Windows 运行时不支持绑定 Setter.Value 的用法(绑定不会评估,并且 Setter 有 没有效果,你不会得到错误,但你不会得到想要的结果 任何一个)。当您从 WPF 或 Silverlight XAML 转换 XAML 样式时, 用设置的字符串或对象替换任何绑定表达式用法 值,或将值重构为共享 StaticResource 标记 扩展值而不是 Binding 获得的值。
解决方法可以是一个辅助类,它带有绑定源路径的附加属性。它在辅助属性的 PropertyChangedCallback 后面的代码中创建绑定:
public class BindingHelper
public static readonly DependencyProperty GridColumnBindingPathProperty =
DependencyProperty.RegisterAttached(
"GridColumnBindingPath", typeof(string), typeof(BindingHelper),
new PropertyMetadata(null, GridBindingPathPropertyChanged));
public static readonly DependencyProperty GridRowBindingPathProperty =
DependencyProperty.RegisterAttached(
"GridRowBindingPath", typeof(string), typeof(BindingHelper),
new PropertyMetadata(null, GridBindingPathPropertyChanged));
public static string GetGridColumnBindingPath(DependencyObject obj)
return (string)obj.GetValue(GridColumnBindingPathProperty);
public static void SetGridColumnBindingPath(DependencyObject obj, string value)
obj.SetValue(GridColumnBindingPathProperty, value);
public static string GetGridRowBindingPath(DependencyObject obj)
return (string)obj.GetValue(GridRowBindingPathProperty);
public static void SetGridRowBindingPath(DependencyObject obj, string value)
obj.SetValue(GridRowBindingPathProperty, value);
private static void GridBindingPathPropertyChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
var propertyPath = e.NewValue as string;
if (propertyPath != null)
var gridProperty =
e.Property == GridColumnBindingPathProperty
? Grid.ColumnProperty
: Grid.RowProperty;
BindingOperations.SetBinding(
obj,
gridProperty,
new Binding Path = new PropertyPath(propertyPath) );
您可以像这样在 XAML 中使用它们:
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="local:BindingHelper.GridColumnBindingPath" Value="Level"/>
<Setter Property="local:BindingHelper.GridRowBindingPath" Value="Row"/>
</Style>
</ItemsControl.ItemContainerStyle>
有关绝对定位的简单解决方法(即绑定Canvas.Left
和canvas.Top
属性),请参阅this answer。
【讨论】:
嗯对我不起作用。 ItemContainerStyle 中的 Targettype 总是 ContentPresenter 吗?如果我将它设置为我的 ViewModel,我会得到一个灾难性的失败异常。 @MatthiasMüller,我认为这是正确的。我有一个类似的问题。 ContentPresenter 是整个模板的父级,所以我相信它是正确的目标类型。 ItemsControl的item容器类型是ContentPresenter,因此ItemContainerStyle的TargetType必须是ContentPresenter。 直接链接到Migration Notes in docs并打开WinUI issue on this topic。【参考方案2】:想从@clemens 添加我对BindingHelper
想法的体验。这是一个很好的解决方案,但我发现当以ListViewItem
为目标时,绑定不会访问底层视图模型。在调试之后,我发现我需要确保绑定是相对于ListViewItem
本身和关联的.Content
属性,以使其能够正确链接到项目的视图模型。
我的特定用例是根据视图模型值设置ListViewItem
的IsTabStop
属性:
private static void BindingPathPropertyChanged(DependencyObject obj,
DependencyPropertyChangedEventArgs e)
if (e.NewValue is string propertyPath)
var binding = new Binding
Path = new PropertyPath($"Content.propertyPath"),
Mode = BindingMode.OneWay,
RelativeSource = new RelativeSource
Mode = RelativeSourceMode.Self
;
BindingOperations.SetBinding(obj, Control.IsTabStopProperty, binding);
如果其他人有问题,希望这会有所帮助。
【讨论】:
以上是关于样式设置器中的 UWP 绑定不起作用的主要内容,如果未能解决你的问题,请参考以下文章