ItemsControl的UWP绑定方向

时间:2019-03-15 17:06:06

标签: uwp

我想创建一个模板化控件,该控件派生自ItemsControl,并且可以根据需要更改其方向。

所以,我尝试了这个:

<Setter Property="ItemsPanel">
    <Setter.Value>
        <ItemsPanelTemplate>
            <ItemsStackPanel Orientation="{Binding Orientation, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
        </ItemsPanelTemplate>
    </Setter.Value>
</Setter>

它没有用,然后我尝试使用Mode = Self,但没有成功。

Orientation是一个DependencyProperty,我已经在.cs文件中声明了它。

我遇到了wpf的旧解决方案,该解决方案使用AncestorType-在UWP中不可用。

我该如何解决这个问题?

谢谢。

1 个答案:

答案 0 :(得分:1)

在UWP中不支持。参见:Setter Class (Windows.UI.Xaml) - Windows UWP applications | Microsoft Docs

  

Windows Presentation Foundation(WPF)和Microsoft Silverlight支持使用Binding表达式为样式中的Setter提供值的功能。 Windows运行时不支持Setter.Value的绑定用法(该绑定不会评估,该Setter无效,您不会收到错误,但也不会获得所需的结果)。从Windows Presentation Foundation(WPF)或Microsoft Silverlight XAML转换XAML样式时,请使用任何设置值的字符串或对象替换任何绑定表达式用法,或将这些值重构为共享的{StaticResource}标记扩展名值,而不是绑定获得的值。< / p>

但是您可以使用attache属性来实现。

在MainPage中添加Orientation属性。

    public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
        "Orientation", typeof(Orientation), typeof(MainPage), new PropertyMetadata(default(Orientation)));

    public Orientation Orientation
    {
        get { return (Orientation) GetValue(OrientationProperty); }
        set { SetValue(OrientationProperty, value); }
    }

添加BindingHelper并定义一个attache属性。

    public static readonly DependencyProperty ItemsPanelOrientationProperty = DependencyProperty.RegisterAttached(
        "ItemsPanelOrientation", typeof(bool), typeof(BindingHelper),
        new PropertyMetadata(default(bool), ItemsPanelOrientation_OnPropertyChanged));

ItemsPanelOrientation_OnPropertyChanged中,将绑定设置为ItemsStackPanel.Orientation。

    private static async void ItemsPanelOrientation_OnPropertyChanged(DependencyObject d,
        DependencyPropertyChangedEventArgs e)
    {
        if (d is ListView listView)
        {
            await listView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                if (listView.ItemsPanelRoot is ItemsStackPanel stackPanel)
                {
                    BindingOperations.SetBinding(stackPanel, ItemsStackPanel.OrientationProperty, new Binding()
                    {
                        Path = new PropertyPath("Orientation"),
                        Mode = BindingMode.OneWay
                    });
                }
            });
        }
    }

在xaml中,编写BindingHelper.ItemsPanelOrientation和ItemsPanelTemplate。

        <ListView.Style>
            <Style TargetType="ListView">
                <Setter Property="ItemsPanel">
                    <Setter.Value>
                        <ItemsPanelTemplate>
                            <ItemsStackPanel Orientation="{Binding Orientation, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
                        </ItemsPanelTemplate>
                    </Setter.Value>
                </Setter>
                <Setter Property="local:BindingHelper.ItemsPanelOrientation" Value="True"></Setter>
            </Style>
        </ListView.Style>

并且您应该在ListView中设置DataContext。 DataContext是名为Page1的Page。

<Page
    x:Class="KeejemairbouLirallpurpallnasfakaw.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:KeejemairbouLirallpurpallnasfakaw"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Name="Page1"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <ListView DataContext="{x:Bind Page1}">
            <ListView.Style>
                <Style TargetType="ListView">
                    <Setter Property="ItemsPanel">
                        <Setter.Value>
                            <ItemsPanelTemplate>
                                <ItemsStackPanel Orientation="{Binding Orientation, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
                            </ItemsPanelTemplate>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="local:BindingHelper.ItemsPanelOrientation" Value="True"></Setter>
                </Style>
            </ListView.Style>
            <ListView.Items>
                <TextBlock Text="1"></TextBlock>
                <TextBlock Text="2"></TextBlock>
                <TextBlock Text="3"></TextBlock>
            </ListView.Items>
        </ListView>
    </Grid>
</Page>

在MainPage中编写代码以更改方向。

    public MainPage()
    {
        this.InitializeComponent();

        Task.Run(async () =>
        {
            while (true)
            {
                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                    () => { Orientation = Orientation.Horizontal; });

                await Task.Delay(TimeSpan.FromSeconds(5));

                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                    () => { Orientation = Orientation.Vertical; });

                await Task.Delay(TimeSpan.FromSeconds(5));
            }
        });
    }

github中的所有代码:https://github.com/lindexi/lindexi_gd/tree/43ee46e847179b61157c5bfbbdec0382ccc97268/KeejemairbouLirallpurpallnasfakaw