我的主页面有appbar,它在不同的页面上共享。我编写了以下代码,在点击gridview项目时打开appbar。
XAML
<AppBar Opened="AppBar_Opened" IsOpen="{Binding IsAppBarOpen}">
后端
private void Clock_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
App.ViewModel.SelectedClock = (Clock)ThemeGridView.SelectedItem;
App.WorldViewModel.IsAppBarOpen = true;
}
private void ThemeGridView_ItemClick(object sender, ItemClickEventArgs e)
{
App.ViewModel.SelectedClock = (Clock)ThemeGridView.SelectedItem;
App.WorldViewModel.IsAppBarOpen = true;
}
WorldViewModel
private bool _IsAppBarOpen;
public bool IsAppBarOpen
{
get { return _IsAppBarOpen; }
set { base.SetProperty(ref _IsAppBarOpen, value); }
}
GridView XAML
<GridView
Grid.Row="1"
Grid.Column="1"
x:Name="ThemeGridView"
ItemsSource="{Binding Clocks}"
ItemTemplate="{StaticResource WorldClockTemplate}"
SelectionChanged="Clock_SelectionChanged"
SelectionMode="None"
IsItemClickEnabled="True"
ItemClick="ThemeGridView_ItemClick"
>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
但是当我选择gridview项目时,appbar没有弹出。没有绑定错误所以它真的很神秘!
答案 0 :(得分:3)
无法绑定IsOpen属性according the msdn:
注意绑定到
IsOpen
属性没有预期的结果 因为PropertyChanged
通知时不会发生 财产设定。
答案 1 :(得分:1)
<AppBar Opened="AppBar_Opened" IsOpen="{Binding IsAppBarOpen, **Mode=TwoWay**}">
答案 2 :(得分:1)
这对我有用。我使用MVVM Light Toolkit。
public bool AppBarIsOpen
{
get { return this._appBarIsOpen; }
set
{
if (this._appBarIsOpen == value) { return; }
this._appBarIsOpen = value;
this.RaisePropertyChanged("AppBarIsOpen"); // without INotifyPropertyChanged it doesn't work
}
}
<AppBar
IsSticky="True"
IsOpen="{Binding Path=AppBarIsOpen, Mode=TwoWay}">
答案 3 :(得分:0)
Roman Weisert的答案正确地指出了它不起作用的可能原因,尽管你也必须像Zack Weiner所说的那样双向绑定(我不确定后者的原因,因为绑定在目标中不起作用无论如何,来源方向)。 AppBar.IsOpen
的当前值可能不会被您的视图模型的IsAppBarOpen
反映出来。如果是这种情况,并且您尝试更新该值,则可能不会引发PropertyChanged
事件,因为您实际上可能没有更新值。相反,您可能只是将值从false
设置为false
或从true
设置为true
。除非有实际更改,否则大多数SetProperty
方法实现不会引发PropertyChanged
事件,并且我认为它们是相同的。
要解决此问题,请考虑按如下方式修改视图模型:
public bool IsAppBarOpen
{
get { return _IsAppBarOpen; } //changes initiated from UI not reflected
set //not updated from UI
{
_IsAppBarOpen = value;
base.OnPropertyChanged();
}
}
bool _IsAppBarOpen;
与视图模型代码的显着区别在于,此处未调用SetProperty
,因此即使后备存储等于新引入的值,也会引发PropertyChanged
。如果你的基类不同,请注意我的方法有一个带有签名的OnPropertyChanged
方法
void OnPropertyChanged( [CallerMemberName] string propertyName = null )
用于举起PropertyChanged
事件。
我可以从你使用代码隐藏中看到,你并没有真正关注MVVM。如果您不关心MVVM,那么您可以完全放弃IsAppBarOpen
属性并直接设置AppBar.IsOpen
。然而,作为一个虔诚地坚持MVVM的人,我不建议你进一步朝着那个(罪恶的)方向前进。
答案 4 :(得分:0)
我遇到了同样的问题并使用Caliburn Micro for WinRT并且这段代码对我有用:
<AppBar IsOpen="{Binding AppBarsOpen}" Name="MainAppBar" Padding="10,0,10,0" AutomationProperties.Name="Bottom App Bar">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<StackPanel x:Name="LeftPanel" Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left">
<Button Name="ShowFlyout" Style="{StaticResource BookmarksAppBarButtonStyle}" />
</StackPanel>
<StackPanel x:Name="RightPanel" Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right">
<Button Style="{StaticResource SaveAppBarButtonStyle}" />
</StackPanel>
</Grid>
</AppBar>
这是ViewModel中的属性:
public bool AppBarsOpen
{
get { return _appBarsOpen; }
set
{
if (value.Equals(_appBarsOpen)) return;
_appBarsOpen = value;
NotifyOfPropertyChange(() => AppBarsOpen);
}
}
答案 5 :(得分:0)
有同样的问题,通过添加Closed事件并从后面的代码更新ViewModel来解决它。由于TwoWay绑定没有像罗马指出的那样起作用,所以别无他法。
XAML
<AppBar x:Name="BottomAppBar1"
AutomationProperties.Name="Bottom App Bar"
Closed="BottomAppBar1_Closed"
IsOpen="{Binding IsOpen, Mode=TwoWay}"
IsSticky="True">
C#代码背后
private void BottomAppBar1_Closed(object sender, object e)
{
MainViewModel vm = this.DataContext as MainViewModel;
vm.IsOpen = false;
}
C#MainViewModel
public const string IsOpenPropertyName = "IsOpen";
private bool isOpen = false;
/// <summary>
/// Sets and gets the IsOpen property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public bool IsOpen
{
get
{
return isOpen;
}
set
{
RaisePropertyChanging(IsOpenPropertyName);
isOpen = value;
RaisePropertyChanged(IsOpenPropertyName);
}
}
答案 6 :(得分:0)
你应该两种方式绑定IsOpen和IsSticky,否则你会遇到问题,例如必须点击两次取消选择一个项目(一次关闭应用栏和一次取消选择),这也有助于你应用栏表现得更加标准(当选择项目时,将阻止应用栏在点按时弹出)。
要显示应用栏,您需要执行以下操作(顺序很重要):
this.IsAppBarSticky = true;
this.IsAppBarOpen = true;
要隐藏它,请执行以下操作:
this.IsAppBarSticky = false;
this.IsAppBarOpen = false;
答案 7 :(得分:0)
使用此工作的另一种方法,无需为app bar关闭事件使用代码隐藏处理程序:
public class AppBarClosedCommand
{
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand),
typeof(AppBarClosedCommand), new PropertyMetadata(null, CommandPropertyChanged));
public static void SetCommand(DependencyObject attached, ICommand value)
{
attached.SetValue(CommandProperty, value);
}
public static ICommand GetCommand(DependencyObject attached)
{
return (ICommand)attached.GetValue(CommandProperty);
}
private static void CommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Attach click handler
(d as AppBar).Closed += AppBar_onClose;
}
private static void AppBar_onClose(object sender, object e)
{
// Get GridView
var appBar = (sender as AppBar);
// Get command
ICommand command = GetCommand(appBar);
// Execute command
command.Execute(e);
}
}
然后在XAML中你可以使用它:
common:AppBarClosedCommand.Command="{Binding AppBarClosedCommand}"
命令功能如下:
public void OnAppBarClosed()
{
AppBarOpen = false;
}