样式设置程序中的UWP绑定不起作用
本文关键字:UWP 绑定 不起作用 设置 程序 样式 | 更新日期: 2023-09-27 18:20:58
我在创建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)或不在运行代码中。怎么了?在"旧的"WPF中,一切都还可以,但在适用于Windows 10的通用应用程序中,我有一个错误。有人能帮我吗?
如MSDN上Setter.Value属性页上的迁移说明一节所述,UWP/Windows Runtime不支持Style Setters中的绑定。
Windows Presentation Foundation(WPF)和Microsoft Silverlight支持使用Binding表达式提供Value对于一种风格的设定者。Windows运行时不支持绑定Setter.Value的用法(绑定不会求值,Setter具有没有效果,你不会出错,但你不会得到想要的结果或者)。从WPF或Silverlight XAML转换XAML样式时,将任何Binding表达式用法替换为字符串或对象值,或者将这些值重构为共享的{StaticResource}标记扩展值,而不是绑定获得的值。
解决方法可以是为绑定的源路径附加属性的帮助程序类。它在helper属性的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
属性),请参阅此答案。
想添加我对@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);
}
}
如果其他人有问题,希望这能有所帮助。