【问题标题】:UWP Binding Orientation of an ItemsControlItemsControl 的 UWP 绑定方向
【发布时间】:2019-03-15 17:06:06
【问题描述】:

我想创建一个模板化控件,它派生自 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 中不可用。

我该如何解决这个问题?

谢谢。

【问题讨论】:

    标签: uwp


    【解决方案1】:

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

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

    但是你可以使用 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 并定义附加属性。

        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
        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

    【讨论】:

      猜你喜欢
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      • 2011-08-30
      • 2018-10-17
      相关资源
      最近更新 更多