如何动态更改列表中基于按钮值的图标?

How to dynamically change the icon on a button based value in a list?

我有以下 xaml 代码:

                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.ContextActions>
                                <MenuItem Text="Check In"
                                      Clicked="CheckInFile"/>
                                <MenuItem Text="Check Out"
                                      Clicked="CheckOutFile"/>
                                <MenuItem Text="Download"
                                      Clicked="DownloadFile"/>
                                <MenuItem Text="Upload Local Copy"
                                      Clicked="UploadFile"/>
                            </ViewCell.ContextActions>

                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="30" />
                                    <RowDefinition Height="30" />
                                </Grid.RowDefinitions>

                                <Label Grid.Column="0" Text="{Binding Path=DriveItem.Name}"
                                   FontSize="Small" />
                                <Label Grid.Column="1""
                                    FontFamily="Segoe MDL2 Assets" 
                                       Text="{Binding PublicationStatus}"
                                     />
                            </Grid>
                        </ViewCell>

                    </DataTemplate>
                </ListView.ItemTemplate>

和相关的cs代码:

   protected override async void OnAppearing()
    {

        var directoryContents = await App.GraphClient.Sites[siteID].Lists[sharedDocsDriveId]
            .Items
            .Request()
            //.Expand(item => item.DriveItem)
            .Expand("driveItem($select=publication,name,id,description,file,webUrl)")
            .GetAsync();

        SharedDocumentList.ItemsSource = directoryContents.CurrentPage.ToList();
      }

对于返回的每个项目,它包含有关文件的信息 - 如果它当前已签出或未签出。该字段是“级别”,如下所示/

directoryContents.CurrentPage[i].DriveItem.Publication
{Microsoft.Graph.PublicationFacet}
    AdditionalData: null
    Level: "checkout"
    ODataType: null
    VersionId: "4.0"

如果 Level 的值为“checkout”,我想使用以下方法显示锁定的图标: https://docs.microsoft.com/en-us/windows/apps/design/style/segoe-ui-symbol-font 但如果它是“已发布”,我想使用解锁图标。

有没有一种简单的方法可以在 XAML 中执行某种 IF 语句来计算 DriveItem.Publication.Level 的值,然后显示适当的图标?我开始尝试在名为 publicationStatus 的代码隐藏中公开一个新的 属性,但是......也许这有点过分了。我觉得有一个我没有想到的更简单的方法?

编辑 1

所以我更新了 xaml 以使用 datatrigger 方法,但我得到的错误是在类型 BindingExtension 中找不到 属性“RelativeSource”。

            <ListView x:Name="SharedDocumentList"
                  HasUnevenRows="true"
                 >
                <ListView.Resources>
                    <Style x:Key="PublicationStatus" TargetType="Label">
                        <Setter Property="FontFamily" Value="Segoe MDL2 Assets" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=Tag, RelativeSource={RelativeSource Self}}"
                                 Value="checkout">
                                <Setter Property="Text" Value="\uE701"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=Tag, RelativeSource={RelativeSource Self}}"
                                Value="published">
                                <Setter Property="Text" Value="\uE702"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ListView.Resources>

                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.ContextActions>
                                <MenuItem Text="Check In"
                                      Clicked="CheckInFile"/>
                                <MenuItem Text="Check Out"
                                      Clicked="CheckOutFile"/>
                                <MenuItem Text="Download"
                                      Clicked="DownloadFile"/>
                                <MenuItem Text="Upload Local Copy"
                                      Clicked="UploadFile"/>
                            </ViewCell.ContextActions>

                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="30" />
                                    <RowDefinition Height="30" />
                                </Grid.RowDefinitions>

                                <Label Grid.Column="0" Text="{Binding Path=DriveItem.Name}"
                                   FontSize="Small" />
                                <Label Grid.Column="1"
                                   Style="{StaticResource PublicationStatus}"
                                   Tag="{Binding PublicationStatus}" />
                            </Grid>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

编辑 2

这是我尝试使用 ValueConverter。

下面是 class 的部分代码:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SPDocumentLibraryContentsPage : ContentPage
{
    public string IconValue { get; set; }
    public SPDocumentLibraryContentsPage()
    {
        InitializeComponent();
        IconValue = "checkout";
        //this.DataContext doesn't exist.
    }

Xaml 页面上的 ListView 如下所示:

                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="30" />
                                    <RowDefinition Height="30" />
                                </Grid.RowDefinitions>

                                <Label Grid.Column="0" Text="{Binding Path=DriveItem.Name}"
                                   FontSize="Small" />
                                <Label x:Name="testBlock" Grid.Column="2"                                      
                                  Text="{Binding IconValue,Converter={StaticResource IconValueConverter}}" FontFamily="Segoe MDL2 Assets" />
                            </Grid>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

而且我能够创建 IconConverter class 没问题。 这里只是一个片段:

 namespace GraphTutorial.Models
 {
     public class IconValueConverter : Xamarin.Forms.IValueConverter
     {
     }

编辑 3

为了得到工作的答案,我做了以下事情:

 <Label Grid.Column="0" Text="{Binding Path=DriveItem.Name}" FontSize="Small" />
 <Label Grid.Column="1" Text="{Binding Path=DriveItem.Publication.Level,Converter={StaticResource IconValueConverter}}" FontFamily="Segoe MDL2 Assets" />

有一种聪明的方法可以通过 TriggerTag 属性 来避免使用 IValueConverter 或从在 Style.

在列表视图或根元素中

<ListView.Resources>
    <Style x:Key="PublicationStatus" TargetType="Label">        
        <Setter Property="FontFamily" Value="Segoe MDL2 Assets" />
        <Style.Triggers>
            <Trigger Property="Tag"
                     Value="checkout">
                <Setter Property="Text" Value="\uE701"/>
            </Trigger>
           <Trigger Property="Tag"
                    Value="published">
                <Setter Property="Text" Value="\uE702"/>
           </Trigger>
        </Style.Triggers>
    </Style>
</ListView.Resources>

然后在代码中:

<Label Grid.Column="1"
       Style="{StaticResource PublicationStatus}"
       Tag="{Binding PublicationStatus}" />

您也可以重复使用一种样式并将其放入某些 ResourceDictionary.

警告。未测试。

您的应用似乎是 Xamarin UWP 应用,而不是本机 UWP 应用。

您也可以尝试在使用绑定时使用 ValueConverter。您需要做的是创建一个 ValueConverter class 并在 ValueConverter 中制定您自己的将不同字符串转换为不同图标的逻辑。 之后,您只需要在绑定中使用 ValueConverter 作为参数即可。

这是我在本机 UWP 应用程序中测试过的示例代码。它应该在 Xamarin UWP 应用程序中工作。您需要将 Textblock 替换为 Label

代码隐藏:

 public class IconValueConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        string OutputValue ;

        string textvalue = value as string;
        if (textvalue.Equals("checkout"))
        {
            OutputValue = "\uE701";
        }
        else if (textvalue.Equals("published"))
        {
            OutputValue = "\uE702";
        }
        else 
        {
            OutputValue = "\uE703";
        }


        return OutputValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

主页:

 public string IconValue { get; set;}

    public MainPage()
    {
        this.InitializeComponent();

        IconValue = "checkout";

        this.BindingContext = this;
    }

Xaml代码:

  <Page.Resources>
    <local:IconValueConverter x:Key="IconValueConverter"/>
</Page.Resources>

<Grid>
    <TextBlock x:Name="MyTextBlcok" Text="{Binding IconValue,Converter={StaticResource IconValueConverter}}" FontFamily="Segoe MDL2 Assets" />
</Grid>