Мое исходное решение заключалось в использовании свойства PrimaryCommands
для привязки команд, но оказалось, что это свойство доступно только для чтения.
Моим решением проблемы будет использование поведения.
Сначала добавьте ссылку на Microsoft.Xaml.Behaviors.Uwp.Managed
из NuGet.
Затем добавьте в свой проект следующее поведение:
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
, которое можно привязать, а также отслеживает события изменения коллекции. Всякий раз, когда происходит изменение, команды перестраиваются.
Наконец, проблема в вашем коде заключается в том, что ваш AppBarButtonList
— это просто поле, а не свойство. Измените это следующим образом:
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 ;}
, который был добавлен перед оператором присваивания.
Теперь вы можете использовать поведение в XAML следующим образом:
<CommandBar>
<interactivity:Interaction.Behaviors>
<local:BindableCommandBarBehavior PrimaryCommands="{Binding Path=Content.AppBarButtonList, ElementName=rootFrame}" />
</interactivity:Interaction.Behaviors>
</CommandBar>
Это ни в коем случае не идеальное решение, и его можно улучшить, чтобы разрешить привязку различных типов коллекций и многое другое, но оно должно охватывать ваш сценарий. Альтернативным решением было бы реализовать пользовательскую версию панели команд с новым дополнительным свойством зависимости непосредственно для типа, но я использовал поведение, чтобы прояснить для пользователя, что это «добавленная» функциональность, а не встроенная. .
person
Martin Zikmund
schedule
22.03.2018