UWP 命令栏绑定 [英] UWP CommandBar Binding

查看:21
本文介绍了UWP 命令栏绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将 UWP CommandBar 绑定到诸如 ObservableCollection 之类的东西?

is it possible to bind an UWP CommandBar to something like a ObservableCollection or so?

我想要实现的是将我的 NavigationViewCommandBar 绑定到特定 Page 的对象,以便 AppBarButton 根据当前 Page

What i want to achieve ist to bind my CommandBar of my NavigationView to an Object of a specific Page so that the AppBarButton change dynamicaly depending on the current Page

我尝试了什么:

MainPage.xaml

    <NavigationView.HeaderTemplate>
        <DataTemplate>
            <Grid>
                <CommandBar Grid.Column="1"
                        HorizontalAlignment="Right"
                        VerticalAlignment="Top"
                        DefaultLabelPosition="Right"
                        Background="{ThemeResource SystemControlBackgroundAltHighBrush}"  Content="{Binding Path=Content.AppBarButtonList, ElementName=rootFrame}">
                </CommandBar>
            </Grid>
        </DataTemplate>
    </NavigationView.HeaderTemplate>

SomePage.xaml.cs

    public ObservableCollection<AppBarButton> AppBarButtonList = new ObservableCollection<AppBarButton> {
        new AppBarButton { Icon = new SymbolIcon(Symbol.Accept), Label="Bla" },
        new AppBarButton{Icon=new SymbolIcon(Symbol.Add),Label="Add"}
    };

但是 CommandBar 什么也没显示.

But the CommandBar shows nothing.

谢谢.

推荐答案

我最初的解决方案是使用 PrimaryCommands 属性来绑定命令,但事实证明该属性是只读的.

My original solution was using the PrimaryCommands property to bind the commands, but it turns out this property is read-only.

我对这个问题的解决方案是使用行为.

My solution to the problem will be using behaviors.

首先从 NuGet 添加对 Microsoft.Xaml.Behaviors.Uwp.Managed 的引用.

First add a reference to Microsoft.Xaml.Behaviors.Uwp.Managed from NuGet.

然后将以下行为添加到您的项目中:

Then add the following behavior to your project:

public class BindableCommandBarBehavior : Behavior<CommandBar>
{
    public ObservableCollection<AppBarButton> PrimaryCommands
    {
        get { return (ObservableCollection<AppBarButton>)GetValue(PrimaryCommandsProperty); }
        set { SetValue(PrimaryCommandsProperty, value); }
    }

    public static readonly DependencyProperty PrimaryCommandsProperty = DependencyProperty.Register(
        "PrimaryCommands", typeof(ObservableCollection<AppBarButton>), typeof(BindableCommandBarBehavior), new PropertyMetadata(default(ObservableCollection<AppBarButton>), UpdateCommands));

    private static void UpdateCommands(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        if (!(dependencyObject is BindableCommandBarBehavior behavior)) return;
        var oldList = dependencyPropertyChangedEventArgs.OldValue as ObservableCollection<AppBarButton>;
        if (dependencyPropertyChangedEventArgs.OldValue != null)
        {
            oldList.CollectionChanged -= behavior.PrimaryCommandsCollectionChanged;
        }

        var newList = dependencyPropertyChangedEventArgs.NewValue as ObservableCollection<AppBarButton>;
        if (dependencyPropertyChangedEventArgs.NewValue != null)
        {
            newList.CollectionChanged += behavior.PrimaryCommandsCollectionChanged;
        }
        behavior.UpdatePrimaryCommands();
    }


    private void PrimaryCommandsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        UpdatePrimaryCommands();
    }


    private void UpdatePrimaryCommands()
    {
        if (PrimaryCommands != null)
        {
            AssociatedObject.PrimaryCommands.Clear();
            foreach (var command in PrimaryCommands)
            {
                AssociatedObject.PrimaryCommands.Add(command);
            }
        }
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        if (PrimaryCommands != null)
        {
            PrimaryCommands.CollectionChanged -= PrimaryCommandsCollectionChanged;
        }
    }
}

这种行为本质上创建了一个假的 PrimaryCommands 属性,它是可绑定的,并且还观察集合更改事件.每当发生更改时,都会重新构建命令.

This behavior essentially creates a fake PrimaryCommands property that is bindable and also observes collection changed events. Whenever a change occurs, the commands are rebuilt.

最后,您代码中的问题是您的 AppBarButtonList 只是一个字段,而不是一个属性.改成这样:

Finally, the problem in your code is that your AppBarButtonList is just a field, not a property. Change it like this:

public ObservableCollection<AppBarButton> AppBarButtonList { get; } = new ObservableCollection<AppBarButton> {
    new AppBarButton { Icon = new SymbolIcon(Symbol.Accept), Label="Bla" },
    new AppBarButton{Icon=new SymbolIcon(Symbol.Add),Label="Add"}
};

注意在赋值运算符之前添加的 {get ;}.

Notice the {get ;} which was added before the assignment operator.

现在您可以像这样使用 XAML 中的行为:

Now you can use the behavior in XAML like this:

<CommandBar>
    <interactivity:Interaction.Behaviors>
        <local:BindableCommandBarBehavior PrimaryCommands="{Binding Path=Content.AppBarButtonList, ElementName=rootFrame}" />
    </interactivity:Interaction.Behaviors>
</CommandBar>

这绝不是一个完美的解决方案,可以改进以允许不同的集合类型绑定等等,但它应该涵盖您的场景.另一种解决方案是实现自定义版本的命令栏,直接在类型上添加新的附加依赖属性,但我使用行为让用户更清楚这是添加"功能,而不是内置功能.

This is by no means a perfect solution and could be improved upon to allow different collection types binding and more, but it should cover your scenario. An alternative solution would be to implement a custom version of command bar, with new additional dependency property directly on the type, but I used behavior to make it clearer for the user that this is an "added" functionality, not a built-in one.

这篇关于UWP 命令栏绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆