【问题标题】:UWP: Why behaviors in DataTemplate has a null AssociatedObject?UWP:为什么 DataTemplate 中的行为有一个空的 AssociatedObject?
【发布时间】:2020-12-02 07:35:19
【问题描述】:

我想将 NavigationView Header 上的 CommandBar 绑定到一个集合以动态显示 AppBarButtons,我使用了this answer 中给出的方法。但是,当我在 DataTemplate 中的 CommandBar 上设置行为并运行程序时,它会引发异常,显示 AssociatedObject 为空。这是代码:
xaml

<i:Interaction.Behaviors>
    <behaviors:NavigationViewHeaderBehavior
        DefaultHeader="{x:Bind ViewModel.Selected.Content, Mode=OneWay}">
        <behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
            <DataTemplate>
                <Grid>
                    <CommandBar Name="headerCommandBar">
                        <i:Interaction.Behaviors>
                            <behaviors:BindableCommandBarBehavior
                                PrimaryCommands="{Binding Path=Content.ViewModel.AppBarButtonList,ElementName=shellFrame, Mode=OneWay}" />
                        </i:Interaction.Behaviors>
                    </CommandBar>
                </Grid>
            </DataTemplate>
        </behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
    </behaviors:NavigationViewHeaderBehavior>
</i:Interaction.Behaviors>

ViewModel 中的 C# 代码:

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

行为准则:

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

    /// <summary>
    /// Update the primary commands for CommandBar.
    /// </summary>
    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;
        }
    }
}

UpdatePrimaryCommands 方法中抛出异常。我想知道为什么会这样。

【问题讨论】:

    标签: c# xaml uwp behavior


    【解决方案1】:

    您的命令在AssociatedObject 实际附加之前更新。在UpdateCommands 中添加AssociatedObject != null 的测试并创建将再次调用UpdateCommands 的方法OnAttached

    /// <summary>
    /// Update the primary commands for CommandBar.
    /// </summary>
    private void UpdatePrimaryCommands()
    {
        if (PrimaryCommands != null && AssociatedObject != null)
        {
            AssociatedObject.PrimaryCommands.Clear();
            foreach (var command in PrimaryCommands)
            {
                AssociatedObject.PrimaryCommands.Add(command);
            }
        }
    }
    
    protected override void OnAttached()
    {
        UpdatePrimaryCommands();
    }
    
    

    【讨论】:

    • 这样就解决了,谢谢你的回复^_^
    猜你喜欢
    • 1970-01-01
    • 2011-06-21
    • 2020-02-07
    • 2016-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    相关资源
    最近更新 更多