【问题标题】:How to dynamically change the icon on a button based value in a list?如何动态更改列表中基于按钮的值的图标?
【发布时间】:2021-12-08 14:50:28
【问题描述】:

我有以下 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 的尝试。

下面是该类的部分代码:

[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 类。 这里只是一个sn-p:

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

【问题讨论】:

    标签: c# xaml uwp


    【解决方案1】:

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

    您也可以在使用绑定时尝试使用ValueConverter。您需要做的是创建一个 ValueConverter 类,并制定自己的逻辑,将不同的字符串转换为 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>
    

    【讨论】:

    • 李,我已经尝试实现....唯一不起作用的是“this.DataContext=this;”线。我没有可用的属性/字段。请参阅编辑 2... 我将很快添加。但是当我构建时没有错误......但是gui上也没有任何显示。 :)
    • 是的,它是一个 Xamarin Forms UWP 应用
    • @dot 好的,这是一个 Xamarin UWP 应用。所以在 Xamarin 中应该是 this.BindingContext=this。我也会更新我的答案
    【解决方案2】:

    有一个聪明的方法可以通过TriggerTag 属性来实现这一点,以避免使用IValueConverter 或从Style 内部访问父DataContext

    在列表视图或根元素内

    <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

    警告。未测试。

    【讨论】:

    • 所以......我回来的错误是在“BindingExtension”类型中找不到“RelativeSource”
    • 查看我的编辑 1
    • @dot 对此我深表歉意。请查看更新的答案
    • 不用担心。我尝试了您更新的解决方案,它也爆炸了。错误是我“缺少“Xamarin.Forms.Trigger”上的强制属性“TargetType”。所以我在两个 元素上都添加了该属性,但随后它抱怨标签对于标签来说是不合法的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-13
    相关资源
    最近更新 更多