如何动态更改列表中基于按钮的值的图标?
Posted
技术标签:
【中文标题】如何动态更改列表中基于按钮的值的图标?【英文标题】: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" />
【问题讨论】:
【参考方案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】:
有一个聪明的方法可以通过Trigger
和Tag
属性来实现这一点,以避免使用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”。所以我在两个以上是关于如何动态更改列表中基于按钮的值的图标?的主要内容,如果未能解决你的问题,请参考以下文章
如何创建多个从同一个数组中获取值的动态下拉列表,而无需更改 Javascript 中的其他下拉列表