opening the appbar in metro style apps using bindi

2019-08-01 20:09发布

My main page has the appbar and it is shared across different pages. I wrote the following code to open the appbar on the click of a gridview item.

XAML

<AppBar Opened="AppBar_Opened" IsOpen="{Binding IsAppBarOpen}">

Back end

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>

But the appbar is not popping up when i select the gridview item. There is no binding error so its really mysterious!

8条回答
时光不老,我们不散
2楼-- · 2019-08-01 20:25

Had the same issue, solved it by adding the Closed event and updating the ViewModel from the code behind. Saw no other way since TwoWay binding was not working as Roman pointed out.

XAML

<AppBar x:Name="BottomAppBar1"
                AutomationProperties.Name="Bottom App Bar"
                Closed="BottomAppBar1_Closed"
                IsOpen="{Binding IsOpen, Mode=TwoWay}"
                IsSticky="True">

C# Code behind

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);
  }
}
查看更多
smile是对你的礼貌
3楼-- · 2019-08-01 20:26
<AppBar Opened="AppBar_Opened" IsOpen="{Binding IsAppBarOpen, **Mode=TwoWay**}">
查看更多
倾城 Initia
4楼-- · 2019-08-01 20:28

There is not way to bind IsOpen property according the msdn:

Note Binding to the IsOpen property doesn't have the expected results because the PropertyChanged notification doesn't occur when the property is set.

查看更多
做个烂人
5楼-- · 2019-08-01 20:31

This works for me. I use 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}">
查看更多
兄弟一词,经得起流年.
6楼-- · 2019-08-01 20:43

I had the same issue and using Caliburn Micro for WinRT and with this code worked for me:

<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>

And that's your property in ViewModel:

public bool AppBarsOpen
{
    get { return _appBarsOpen; }
    set
    {
        if (value.Equals(_appBarsOpen)) return;
        _appBarsOpen = value;
        NotifyOfPropertyChange(() => AppBarsOpen);
    }
}
查看更多
Luminary・发光体
7楼-- · 2019-08-01 20:45

Another way to make this work without having to use a codebehind handler for app bar closed event:

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

then in the XAML you can use it like :

common:AppBarClosedCommand.Command="{Binding AppBarClosedCommand}"

with the command function looking like:

public void OnAppBarClosed()
    {
        AppBarOpen = false;
    }
查看更多
登录 后发表回答