【问题标题】:Shell dynamically hide ShellItem in Flyout MenuShell 在 Flyout 菜单中动态隐藏 ShellItem
【发布时间】:2021-06-21 23:53:01
【问题描述】:

是否有动态将IsVisible 设置为ShellItem 的解决方案?我必须解决以下问题:我有一个弹出菜单,其中包含ShellItem,一个是登录,另一个是注销。

<ShellItem x:Name="LoginItem" Route="login" Title="{resources:Translate Login}" Icon="icon_LogIn.png" >
    <ShellContent ContentTemplate="{DataTemplate views:Account.LoginPage}"/>
</ShellItem>

<ShellItem x:Name="LogoutItem" Route="Logout" Title="{resources:Translate Logout}" Icon="icon_logOut.png" >
    <ShellContent ContentTemplate="{DataTemplate views:Account.SignOutPage}"/>
</ShellItem>

现在不必在弹出菜单中看到它们。如果用户已登录,则只有注销项可见。如果用户没有登录,只有“登录”项应该是可见的。正如我所见,弹出菜单是在应用程序启动时构建的,然后再也不会出现,那么我该如何实现呢?而且没有ShellItem.Behavior等。

顺便问一下,ShellItemFlyoutItem 有什么区别?

【问题讨论】:

    标签: xaml xamarin xamarin.forms xamarin.forms.shell


    【解决方案1】:

    在您的 AppShell.xaml.cs 中创建和管理一个反映身份验证状态的属性IsUserAuthenticated 绑定到IsVisible

    InvertedBoolConverter 来自Xamarin.CommunityToolkit package

    <Shell.Resource>
       <ResourceDictionary>
           <xct:InvertedBoolConverter x:Key="InvertedBoolConverter" />
       </ResourceDictionary>
    </Shell.Resource>
    
    
    <ShellItem x:Name="LoginItem" Route="login" Title="{resources:Translate Login}" Icon="icon_LogIn.png"
               IsVisible="{Binding IsUserAuthenticated,
                           Converter={StaticResource InvertedBoolConverter}}">
        <ShellContent ContentTemplate="{DataTemplate views:Account.LoginPage}"/>
    </ShellItem>
    
    <ShellItem x:Name="LogoutItem" Route="Logout" Title="{resources:Translate Logout}" Icon="icon_logOut.png"
               IsVisible="{Binding IsUserAuthenticated}">
        <ShellContent ContentTemplate="{DataTemplate views:Account.SignOutPage}"/>
    </ShellItem>
    

    相关问题

    How can you restrict/control the navigation routes the user can visit based on login status/role?

    【讨论】:

      【解决方案2】:

      您可以使用&lt;Shell.FlyoutHeaderTemplate&gt; 添加自定义菜单项,然后使用绑定隐藏/显示菜单。

      步骤 1. 实现 InverseBoolConverter 类

      namespace MyMobileApp.Converters
      {
          public class InverseBoolConverter : Xamarin.Forms.IValueConverter
          {
              public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
              {
                  return !(bool)value;
              }
              public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
              {
                  return !(bool)value;
              }
          }
      }
      

      第 2 步:在 AppShell.xaml 类中添加 InverseBoolConverter 引用。然后在顶部添加 xmlns:converter="clr-namespace:MyMobileApp.Converters"(在 Shell 标记内)。然后在&lt;ResourceDictionary&gt; 标签之后添加&lt;converter:InverseBoolConverter x:Key="cvInverse"&gt;&lt;/converter:InverseBoolConverter&gt;

      第 3 步:在 AppShell.xaml 中的 &lt;/FlyoutItem&gt; 标记之后添加以下代码。

      <Shell.FlyoutHeaderTemplate>
          <DataTemplate>
              <StackLayout BackgroundColor="White">
                  <!--Header-->
                  <StackLayout Orientation="Horizontal" BackgroundColor="LightGray" Padding="20" IsVisible="{Binding IsUserLogedin}">
                      <Label Text="Watchlist" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" VerticalTextAlignment="Center">
                          <Label.GestureRecognizers>
                              <TapGestureRecognizer Command="{Binding WatchlistCommand}"/>
                          </Label.GestureRecognizers>
                      </Label>
                      <Label Text="Logout" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="End" VerticalTextAlignment="Center">
                          <Label.GestureRecognizers>
                              <TapGestureRecognizer Command="{Binding LogoutCommand}"/>
                          </Label.GestureRecognizers>
                      </Label>
                  </StackLayout>
                  <StackLayout Orientation="Horizontal" BackgroundColor="LightGray" Padding="20" IsVisible="{Binding IsUserLogedin, Converter={StaticResource cvInverse}}">
                      <Label Text="Register" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" VerticalTextAlignment="Center">
                          <Label.GestureRecognizers>
                              <TapGestureRecognizer Command="{Binding RegisterCommand}"/>
                          </Label.GestureRecognizers>
                      </Label>
                      <Label Text="Login" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="End" VerticalTextAlignment="Center">
                          <Label.GestureRecognizers>
                              <TapGestureRecognizer Command="{Binding LoginCommand}"/>
                          </Label.GestureRecognizers>
                      </Label>
                  </StackLayout>
              </StackLayout>
          </DataTemplate>
      </Shell.FlyoutHeaderTemplate>
      

      第 4 步:在 AppShell.xaml.cs 类中实现绑定

      public Xamarin.Forms.Command LoginCommand { get; }
      public Xamarin.Forms.Command RegisterCommand { get; }
      public Xamarin.Forms.Command LogoutCommand { get; }
      public Xamarin.Forms.Command WatchlistCommand { get; }
      
      private bool _isUserLoggedIn;
      public bool IsUserLogedin
      {
          get => _isUserLoggedIn;
          set => SetProperty(ref _isUserLoggedIn, value);
      }
      public AppShell()
      {   
          InitializeComponent();  
          LoginCommand = new Xamarin.Forms.Command(MenuClicked);
          RegisterCommand = new Xamarin.Forms.Command(MenuClicked);
          LogoutCommand = new Xamarin.Forms.Command(MenuClicked);
          WatchlistCommand = new Xamarin.Forms.Command(MenuClicked);
          BindingContext = this;
      }
      private async void MenuClicked(object obj)
      {
          
      }
      protected bool SetProperty<T>(ref T backingStore, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "", System.Action onChanged = null)
              {
                  if (System.Collections.Generic.EqualityComparer<T>.Default.Equals(backingStore, value))
                      return false;
      
                  backingStore = value;
                  onChanged?.Invoke();
                  OnPropertyChanged(propertyName);
                  return true;
              }
      

      【讨论】:

        猜你喜欢
        • 2020-12-18
        • 2017-12-16
        • 1970-01-01
        • 2012-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-18
        相关资源
        最近更新 更多