样式设置器中的UWP绑定无法正常工作

时间:2015-11-06 19:08:45

标签: c# xaml win-universal-app setter itemcontainerstyle

我在创建xaml控件时遇到问题。我在通用应用程序中在VS 2015中编写新项目。我想创建网格。在这个网格中我想要一个按钮。在模型中,我指定了列(Level)和Row。 这是我的代码:

<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中没有运行代码。 怎么了?在&#34; old&#34; WPF一切正常,但在Universal App for Windows 10中我出错了。 谁能帮我 ?

2 个答案:

答案 0 :(得分:25)

如MSDN上Setter.Value property页面上的迁移说明部分所述,UWP / Windows运行时不支持样式设置器中的绑定。

  

Windows Presentation Foundation(WPF)和Microsoft Silverlight   支持使用Binding表达式提供Value的功能   对于风格的二传手。 Windows运行时不支持绑定   Setter.Value的用法(Binding不会评估和Setter有   没有效果,你不会得到错误,但你不会得到想要的结果   其一)。从WPF或Silverlight XAML转换XAML样式时,   用设置的字符串或对象替换任何Binding表达式用法   值,或将值重构为共享{StaticResource}标记   扩展值而不是Binding获得的值。

变通方法可以是一个辅助类,它具有绑定源路径的附加属性。它在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.Leftcanvas.Top属性),请参阅this answer

答案 1 :(得分:1)

想要从@clemens中添加我对这个BindingHelper想法的体验。这是一个简洁的解决方案,但我发现,当定位ListViewItem时,绑定将无法访问基础视图模型。调试之后,我发现我需要确保绑定是相对于ListViewItem本身和相关的.Content属性,以使其能够正确链接到项目的视图模型。

我的特定用例是根据视图模型值设置IsTabStop的{​​{1}}属性:

ListViewItem

希望如果其他人遇到问题,这会有所帮助。