Muzib
Muzib

Reputation: 2581

UWP Binding Orientation of an ItemsControl

I wanted to create a templated control, which derives from ItemsControl and will be able to change it's orientation if needed.

So, I tried this:

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

It didn't work, then I tried with Mode = Self, no success.

Orientation is a DependencyProperty, which I have declared in the .cs file.

I have come across an old solution for wpf, which uses AncestorType - not available in UWP.

How can I solve this problem?

Thanks.

Upvotes: 0

Views: 309

Answers (1)

lindexi
lindexi

Reputation: 4327

That is no support in UWP. See: Setter Class (Windows.UI.Xaml) - Windows UWP applications | Microsoft Docs

Windows Presentation Foundation (WPF) and Microsoft Silverlight supported the ability to use a Binding expression to supply the Value for a Setter in a Style. The Windows Runtime doesn't support a Binding usage for Setter.Value (the Binding won't evaluate and the Setter has no effect, you won't get errors, but you won't get the desired result either). When you convert XAML styles from Windows Presentation Foundation (WPF) or Microsoft Silverlight XAML, replace any Binding expression usages with strings or objects that set values, or refactor the values as shared {StaticResource} markup extension values rather than Binding -obtained values.

But you can use attache property to do it.

Adding the Orientation property in MainPage.

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

Adding the BindingHelper and define a attache property.

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

In the ItemsPanelOrientation_OnPropertyChanged set the bind to 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
                    });
                }
            });
        }
    }

In xaml, writing the BindingHelper.ItemsPanelOrientation and the 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>

And you should set the DataContext in ListView. The DataContext is the Page that name as 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>

Writing the code in MainPage to change the Orientation.

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

All the code in github: https://github.com/lindexi/lindexi_gd/tree/43ee46e847179b61157c5bfbbdec0382ccc97268/KeejemairbouLirallpurpallnasfakaw

Upvotes: 1

Related Questions