Связывание UWP в Style Setter не работает

У меня проблема с созданием элемента управления 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 все было в порядке, но в Universal App для Windows 10 у меня ошибка. Может кто-нибудь мне помочь ?

12 голосов | спросил Babel 6 52015vEurope/Moscow11bEurope/MoscowFri, 06 Nov 2015 22:08:44 +0300 2015, 22:08:44

2 ответа


0

Как отмечено в разделе Примечания по миграции на Страница свойства Setter.Value на MSDN, среда выполнения UWP /Windows не поддерживает привязки в установщиках стилей.

  

Windows Presentation Foundation (WPF) и Microsoft Silverlight   поддерживается возможность использовать выражение Binding для предоставления значения   для сеттера в стиле. Среда выполнения Windows не поддерживает привязку   использование для Setter.Value (привязка не будет оценена, а Setter имеет   безрезультатно, вы не получите ошибок, но вы не получите желаемого результата   или). При преобразовании стилей XAML из WPF или Silverlight XAML   заменить любое использование выражения Binding на строки или объекты, которые устанавливают   значения или изменить их значения как общую разметку {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, см. этот ответ .

ответил Clemens 7 62015vEurope/Moscow11bEurope/MoscowSat, 07 Nov 2015 14:48:18 +0300 2015, 14:48:18
0

Хотел добавить свой опыт этой BindingHelper из @clemens. Это изящное решение, но я обнаружил, что при нацеливании на ListViewItem привязка не будет обращаться к базовой модели представления. После отладки я обнаружил, что мне нужно убедиться, что привязка связана с самим ListViewItem и связанным с ним .Content для правильной ссылки на модель представления элемента.

Мой конкретный вариант использования состоял в том, чтобы установить свойство IsTabStop для ListViewItem на основе значения модели представления:

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);
    }
}

Надеюсь, это поможет, если у кого-то еще есть проблема.

ответил Colin B 12 Jpm1000000pmFri, 12 Jan 2018 21:23:00 +030018 2018, 21:23:00

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132