使用绑定属性打开appbar在Metro风格应用程序(opening the appbar in m

2019-10-17 06:09发布

我的主页有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>

但appbar没有弹出时,我选择gridview的项目。 有那么它真的玄无约束力的错误!

Answer 1:

没有绑定IsOpen属性的方式根据MSDN :

注意绑定到IsOpen属性,因为没有预期结果PropertyChanged当属性设置不会发生的通知。



Answer 2:

<AppBar Opened="AppBar_Opened" IsOpen="{Binding IsAppBarOpen, **Mode=TwoWay**}">


Answer 3:

这对我的作品。 我使用MVVM光工具包。

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


Answer 4:

罗马Weisert的答案正确地指出了可能的原因是没有工作,但同时也必须结合双向如扎克·韦纳建议(我不知道,因为结合了后者的原因是没有在目标TO-工作源方向反正)。 的当前值AppBar.IsOpen可能不反映IsAppBarOpen您的视图模型。 如果是这样的话,你尝试更新的价值,它可能是没有PropertyChanged事件引发的,因为你实际上可能没有更新的值。 相反,你可能只是其值设置从falsefalsetruetrue 。 大多数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,但是,我不建议你进一步头在(有罪)的方向。



Answer 5:

我有同样的问题,并使用卡利科技进行的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>

这就是在视图模型你的财产:

public bool AppBarsOpen
{
    get { return _appBarsOpen; }
    set
    {
        if (value.Equals(_appBarsOpen)) return;
        _appBarsOpen = value;
        NotifyOfPropertyChange(() => AppBarsOpen);
    }
}


Answer 6:

有同样的问题,通过增加Closed事件,并从代码更新视图模型背后解决它。 认为没有别的办法,因为双向绑定是不工作作为罗马指出。

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


Answer 7:

你应该结合两者ISOPEN和IsSticky双向的,否则你将得到与具有挖掘两个时间取消选择的项目例题(一次可关闭应用程序栏和一次取消选择)以及它的将有助于让你的应用程序栏的行为更standarly(将防止应用栏当选择的项目弹出向下敲击)。
要显示应用栏,你需要做以下(顺序很重要):

this.IsAppBarSticky = true;
this.IsAppBarOpen = true;

而将其隐藏,请执行以下操作:

this.IsAppBarSticky = false;
this.IsAppBarOpen = false;


Answer 8:

另一种方式来完成这项工作,而不必使用代码隐藏处理程序应用程序栏关闭事件:

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


文章来源: opening the appbar in metro style apps using binding property